Merge pull request #167 from nfi/contrib/coap-lwm2m-dtls

Updated CoAP and LWM2M with added DTLS support
This commit is contained in:
Simon Duquennoy 2018-02-01 10:27:36 +01:00 committed by GitHub
commit 0971088260
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
164 changed files with 10693 additions and 6170 deletions

6
.gitmodules vendored
View File

@ -13,3 +13,9 @@
[submodule "tools/cooja"]
path = tools/cooja
url = https://github.com/contiki-ng/cooja.git
[submodule "os/net/security/tinydtls"]
path = os/net/security/tinydtls
url = https://github.com/contiki-ng/tinydtls.git
[submodule "tests/18-coap-lwm2m/example-lwm2m-standalone"]
path = tests/18-coap-lwm2m/example-lwm2m-standalone
url = https://github.com/contiki-ng/example-lwm2m-standalone.git

View File

@ -26,6 +26,7 @@ env:
- TEST_NAME='rpl-lite'
- TEST_NAME='rpl-classic'
- TEST_NAME='tun-rpl-br'
- TEST_NAME='coap-lwm2m'
- TEST_NAME='simulation-base'
- TEST_NAME='ieee802154'
- TEST_NAME='compile-nxp-ports'

View File

@ -360,6 +360,9 @@ viewconf:
@echo "##### \"MAKE_MAC\": ______________________________ $(MAKE_MAC)"
@echo "##### \"MAKE_NET\": ______________________________ $(MAKE_NET)"
@echo "##### \"MAKE_ROUTING\": __________________________ $(MAKE_ROUTING)"
ifdef MAKE_COAP_DTLS_KEYSTORE
@echo "##### \"MAKE_COAP_DTLS_KEYSTORE\": _______________ $(MAKE_COAP_DTLS_KEYSTORE)"
endif
@echo "----------------- C variables: -----------------"
$(Q)$(CC) $(CFLAGS) -E $(CONTIKI)/tools/viewconf.c | grep \#\#\#\#\#
@echo "------------------------------------------------"

View File

@ -9,24 +9,13 @@ ifeq ($(TARGET),native)
MODULES_REL += ./resources-plugtest
endif
MODULES_REL += ./resources
MODULES_REL += $(TARGET)
# Include the CoAP implementation
MODULES += os/net/app-layer/coap
# optional rules to get assembly
#CUSTOM_RULE_C_TO_OBJECTDIR_O = 1
#CUSTOM_RULE_S_TO_OBJECTDIR_O = 1
include $(CONTIKI)/Makefile.include
# optional rules to get assembly
#$(OBJECTDIR)/%.o: asmdir/%.S
# $(CC) $(CFLAGS) -MMD -c $< -o $@
# @$(FINALIZE_DEPENDENCY)
#
#asmdir/%.S: %.c
# $(CC) $(CFLAGS) -MMD -S $< -o $@
# border router rules
$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c
(cd $(CONTIKI)/tools && $(MAKE) tunslip6)
@ -37,8 +26,8 @@ connect-router: $(CONTIKI)/tools/tunslip6
connect-router-cooja: $(CONTIKI)/tools/tunslip6
sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 -p 60001 fd00::1/64
connect-router-native: $(CONTIKI)/examples/native-border-router/border-router.native
sudo $(CONTIKI)/examples/native-border-router/border-router.native -a 127.0.0.1 -p 60001 fd00::1/64
connect-router-native: $(CONTIKI)/examples/rpl-border-router/border-router.native
sudo $(CONTIKI)/examples/rpl-border-router/border-router.native -a 127.0.0.1 -p 60001 fd00::1/64
connect-minimal:
sudo ip address add fdfd::1/64 dev tap0
connect-native:
sudo ip address add fdfd::1/64 dev tun0

View File

@ -1,109 +1,44 @@
A Quick Introduction to the Erbium (Er) REST Engine
A Quick Introduction to the Erbium (Er) CoAP Engine
===================================================
EXAMPLE FILES
-------------
- coap-example-server.c: A RESTful server example showing how to use the REST
layer to develop server-side applications (at the moment only CoAP is
implemented for the REST Engine).
- coap-example-server.c: A CoAP server example showing how to use the CoAP
layer to develop server-side applications.
- coap-example-client.c: A CoAP client that polls the /actuators/toggle resource
every 10 seconds and cycles through 4 resources on button press (target
address is hard-coded).
- plugtest-server.c: The server used for draft compliance testing at ETSI
IoT CoAP Plugtests. Erbium (Er) participated in Paris, France, March 2012 and
Sophia-Antipolis, France, November 2012 (configured for minimal-net).
Sophia-Antipolis, France, November 2012 (configured for native).
PRELIMINARIES
-------------
- Make sure rpl-border-router has the same stack and fits into mote memory:
You can disable RDC in border-router project-conf.h (not really required as BR keeps radio turned on).
#define NETSTACK_CONF_RDC nullrdc_driver
- Alternatively, you can use the native-border-router together with the slip-radio.
- For convenience, define the Cooja addresses in /etc/hosts
fd00::0212:7401:0001:0101 cooja1
fd00::0212:7402:0002:0202 cooja2
...
- Get the Copper (Cu) CoAP user-agent from
[https://addons.mozilla.org/en-US/firefox/addon/copper-270430](https://addons.mozilla.org/en-US/firefox/addon/copper-270430)
- Optional: Save your target as default target
make TARGET=sky savetarget
COOJA HOWTO
-----------
TMOTE SKY HOWTO
---------------
###Server only:
The CoAP example no longer fits in the limited ROM of the Tmote Sky.
Please use a platform with larger ROM instead.
make TARGET=cooja server-only.csc
Open new terminal
make connect-router-cooja
- Start Copper and discover resources at coap://cooja2:5683/
- Choose "Click button on Sky 2" from the context menu of mote 2 (server) after
requesting /test/separate
- Do the same when observing /test/event
###With client:
make TARGET=cooja server-client.csc
Open new terminal
make connect-router-cooja
- Wait until red LED toggles on mote 2 (server)
- Choose "Click button on Sky 3" from the context menu of mote 3 (client) and
watch serial output
TMOTES HOWTO
NATIVE HOWTO
------------
###Server:
1. Connect two Tmote Skys (check with $ make TARGET=sky sky-motelist)
make TARGET=sky coap-example-server.upload MOTE=2
make TARGET=sky login MOTE=2
2. Press reset button, get address, abort with Ctrl+C:
Line: "Tentative link-local IPv6 address fe80:0000:0000:0000:____:____:____:____"
cd ../rpl-border-router/
make TARGET=sky border-router.upload MOTE=1
make connect-router
For a BR tty other than USB0:
make connect-router-port PORT=X
3. Start Copper and discover resources at:
coap://[fd00::____:____:____:____]:5683/
### Add a client:
1. Change the hard-coded server address in coap-example-client.c to fd00::____:____:____:____
2. Connect a third Tmote Sky
make TARGET=sky coap-example-client.upload MOTE=3
MINIMAL-NET HOWTO
-----------------
With the target minimal-net you can test your CoAP applications without
With the target native you can test your CoAP applications without
constraints, i.e., with large buffers, debug output, memory protection, etc.
The plugtest-server is thought for the minimal-net platform, as it requires
The plugtest-server is thought for the native platform, as it requires
an 1280-byte IP buffer and 1024-byte blocks.
make TARGET=minimal-net plugtest-server
sudo ./plugtest-server.minimal-net
make TARGET=native plugtest-server
sudo ./plugtest-server.native
Open new terminal
make connect-minimal
make connect-native
- Start Copper and discover resources at coap://[fdfd::ff:fe00:10]:5683/
- You can enable the ETSI Plugtest menu in Copper's preferences
@ -130,12 +65,12 @@ in coap-example-server.c. In general, coap supports:
- All draft-18 header options
- CON Retransmissions (note COAP_MAX_OPEN_TRANSACTIONS)
- Blockwise Transfers (note REST_MAX_CHUNK_SIZE, see plugtest-server.c for
- Blockwise Transfers (note COAP_MAX_CHUNK_SIZE, see plugtest-server.c for
Block1 uploads)
- Separate Responses (no rest_set_pre_handler() required anymore, note
coap_separate_accept(), _reject(), and _resume())
- Resource Discovery
- Observing Resources (see EVENT_ and PRERIODIC_RESOURCE, note
- Observing Resources (see EVENT_ and PERIODIC_RESOURCE, note
COAP_MAX_OBSERVERS)
TODOs

View File

@ -42,33 +42,22 @@
#include "contiki.h"
#include "contiki-net.h"
#include "coap-engine.h"
#include "coap-blocking-api.h"
#include "dev/button-sensor.h"
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#define PRINTLLADDR(addr)
#endif
/* Log configuration */
#include "coap-log.h"
#define LOG_MODULE "client"
#define LOG_LEVEL LOG_LEVEL_COAP
/* FIXME: This server address is hard-coded for Cooja and link-local for unconnected border router. */
#define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7402, 0x0002, 0x0202) /* cooja2 */
/* #define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xbbbb, 0, 0, 0, 0, 0, 0, 0x1) */
#define LOCAL_PORT UIP_HTONS(COAP_DEFAULT_PORT + 1)
#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT)
#define SERVER_EP "coap://[fe80::212:7402:0002:0202]"
#define TOGGLE_INTERVAL 10
PROCESS(er_example_client, "Erbium Example Client");
AUTOSTART_PROCESSES(&er_example_client);
uip_ipaddr_t server_ipaddr;
static struct etimer et;
/* Example URIs that can be queried. */
@ -82,7 +71,7 @@ static int uri_switch = 0;
/* This function is will be passed to COAP_BLOCKING_REQUEST() to handle responses. */
void
client_chunk_handler(void *response)
client_chunk_handler(coap_message_t *response)
{
const uint8_t *chunk;
@ -92,14 +81,15 @@ client_chunk_handler(void *response)
}
PROCESS_THREAD(er_example_client, ev, data)
{
coap_endpoint_t server_ep;
PROCESS_BEGIN();
static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */
static coap_message_t request[1]; /* This way the packet can be treated as pointer as usual. */
SERVER_NODE(&server_ipaddr);
coap_endpoint_parse(SERVER_EP, strlen(SERVER_EP), &server_ep);
/* receives all CoAP messages */
coap_init_engine();
coap_engine_init();
etimer_set(&et, TOGGLE_INTERVAL * CLOCK_SECOND);
@ -122,11 +112,10 @@ PROCESS_THREAD(er_example_client, ev, data)
coap_set_payload(request, (uint8_t *)msg, sizeof(msg) - 1);
PRINT6ADDR(&server_ipaddr);
PRINTF(" : %u\n", UIP_HTONS(REMOTE_PORT));
LOG_INFO_COAP_EP(&server_ep);
LOG_INFO_("\n");
COAP_BLOCKING_REQUEST(&server_ipaddr, REMOTE_PORT, request,
client_chunk_handler);
COAP_BLOCKING_REQUEST(&server_ep, request, client_chunk_handler);
printf("\n--Done--\n");
@ -142,10 +131,10 @@ PROCESS_THREAD(er_example_client, ev, data)
printf("--Requesting %s--\n", service_urls[uri_switch]);
PRINT6ADDR(&server_ipaddr);
PRINTF(" : %u\n", UIP_HTONS(REMOTE_PORT));
LOG_INFO_COAP_EP(&server_ep);
LOG_INFO_("\n");
COAP_BLOCKING_REQUEST(&server_ipaddr, REMOTE_PORT, request,
COAP_BLOCKING_REQUEST(&server_ep, request,
client_chunk_handler);
printf("\n--Done--\n");

View File

@ -49,19 +49,8 @@
#if DEBUG
#define PRINTF(...) printf(__VA_ARGS__)
#define PRINTFLN(format, ...) printf(format "\n", ##__VA_ARGS__)
#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:" \
"%02x%02x:%02x%02x:%02x%02x:%02x%02x]", \
((uint8_t *)addr)[0], ((uint8_t *)addr)[1], \
((uint8_t *)addr)[2], ((uint8_t *)addr)[3], \
((uint8_t *)addr)[4], ((uint8_t *)addr)[5], \
((uint8_t *)addr)[6], ((uint8_t *)addr)[7], \
((uint8_t *)addr)[8], ((uint8_t *)addr)[9], \
((uint8_t *)addr)[10], ((uint8_t *)addr)[11], \
((uint8_t *)addr)[12], ((uint8_t *)addr)[13], \
((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#define PRINTFLN(...)
#endif

View File

@ -31,7 +31,7 @@
/**
* \file
* Erbium (Er) REST Engine example.
* Erbium (Er) CoAP Engine example.
* \author
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
@ -40,8 +40,7 @@
#include <stdlib.h>
#include <string.h>
#include "contiki.h"
#include "contiki-net.h"
#include "rest-engine.h"
#include "coap-engine.h"
#if PLATFORM_HAS_BUTTON
#include "dev/button-sensor.h"
@ -51,19 +50,15 @@
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#define PRINTLLADDR(addr)
#endif
/*
* Resources to be activated need to be imported through the extern keyword.
* The build system automatically compiles the resources in the corresponding sub-directory.
*/
extern resource_t
extern coap_resource_t
res_hello,
res_mirror,
res_chunks,
@ -73,29 +68,29 @@ extern resource_t
res_sub,
res_b1_sep_b2;
#if PLATFORM_HAS_LEDS
extern resource_t res_leds, res_toggle;
extern coap_resource_t res_leds, res_toggle;
#endif
#if PLATFORM_HAS_LIGHT
#include "dev/light-sensor.h"
extern resource_t res_light;
extern coap_resource_t res_light;
#endif
#if PLATFORM_HAS_BATTERY
#include "dev/battery-sensor.h"
extern resource_t res_battery;
extern coap_resource_t res_battery;
#endif
#if PLATFORM_HAS_TEMPERATURE
#include "dev/temperature-sensor.h"
extern resource_t res_temperature;
extern coap_resource_t res_temperature;
#endif
/*
extern resource_t res_battery;
extern coap_resource_t res_battery;
#endif
#if PLATFORM_HAS_RADIO
extern resource_t res_radio;
extern coap_resource_t res_radio;
#endif
#if PLATFORM_HAS_SHT11
#include "dev/sht11/sht11-sensor.h"
extern resource_t res_sht11;
extern coap_resource_t res_sht11;
#endif
*/
@ -120,47 +115,49 @@ PROCESS_THREAD(er_example_server, ev, data)
PRINTF("uIP buffer: %u\n", UIP_BUFSIZE);
PRINTF("LL header: %u\n", UIP_LLH_LEN);
PRINTF("IP+UDP header: %u\n", UIP_IPUDPH_LEN);
PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE);
PRINTF("CoAP max chunk: %u\n", COAP_MAX_CHUNK_SIZE);
/* Initialize the REST engine. */
rest_init_engine();
coap_engine_init();
/*
* Bind the resources to their Uri-Path.
* WARNING: Activating twice only means alternate path, not two instances!
* All static variables are the same for each URI path.
*/
rest_activate_resource(&res_hello, "test/hello");
/* rest_activate_resource(&res_mirror, "debug/mirror"); */
/* rest_activate_resource(&res_chunks, "test/chunks"); */
/* rest_activate_resource(&res_separate, "test/separate"); */
rest_activate_resource(&res_push, "test/push");
/* rest_activate_resource(&res_event, "sensors/button"); */
/* rest_activate_resource(&res_sub, "test/sub"); */
/* rest_activate_resource(&res_b1_sep_b2, "test/b1sepb2"); */
coap_activate_resource(&res_hello, "test/hello");
coap_activate_resource(&res_mirror, "debug/mirror");
coap_activate_resource(&res_chunks, "test/chunks");
coap_activate_resource(&res_separate, "test/separate");
coap_activate_resource(&res_push, "test/push");
#if PLATFORM_HAS_BUTTON
coap_activate_resource(&res_event, "sensors/button");
#endif /* PLATFORM_HAS_BUTTON */
coap_activate_resource(&res_sub, "test/sub");
coap_activate_resource(&res_b1_sep_b2, "test/b1sepb2");
#if PLATFORM_HAS_LEDS
/* rest_activate_resource(&res_leds, "actuators/leds"); */
rest_activate_resource(&res_toggle, "actuators/toggle");
/* coap_activate_resource(&res_leds, "actuators/leds"); */
coap_activate_resource(&res_toggle, "actuators/toggle");
#endif
#if PLATFORM_HAS_LIGHT
rest_activate_resource(&res_light, "sensors/light");
SENSORS_ACTIVATE(light_sensor);
coap_activate_resource(&res_light, "sensors/light");
SENSORS_ACTIVATE(light_sensor);
#endif
#if PLATFORM_HAS_BATTERY
rest_activate_resource(&res_battery, "sensors/battery");
SENSORS_ACTIVATE(battery_sensor);
coap_activate_resource(&res_battery, "sensors/battery");
SENSORS_ACTIVATE(battery_sensor);
#endif
#if PLATFORM_HAS_TEMPERATURE
rest_activate_resource(&res_temperature, "sensors/temperature");
SENSORS_ACTIVATE(temperature_sensor);
coap_activate_resource(&res_temperature, "sensors/temperature");
SENSORS_ACTIVATE(temperature_sensor);
#endif
/*
#if PLATFORM_HAS_RADIO
rest_activate_resource(&res_radio, "sensors/radio");
coap_activate_resource(&res_radio, "sensors/radio");
#endif
#if PLATFORM_HAS_SHT11
rest_activate_resource(&res_sht11, "sensors/sht11");
SENSORS_ACTIVATE(sht11_sensor);
coap_activate_resource(&res_sht11, "sensors/sht11");
SENSORS_ACTIVATE(sht11_sensor);
#endif
*/

View File

@ -1,10 +0,0 @@
21,23c21
< #ifdef __INSIDE_CYGWIN__
< uint32_t __s6_addr32[4];
< #endif
---
> u_int __s6_addr32[4];
36d33
< #ifdef __INSIDE_CYGWIN__
39d35
< #endif

View File

@ -44,7 +44,7 @@
#include "coap.h"
#include "coap-transactions.h"
#include "coap-separate.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "plugtest.h"
/*
@ -52,7 +52,7 @@
* The build system automatically compiles the resources in the corresponding
* sub-directory.
*/
extern resource_t
extern coap_resource_t
res_plugtest_test,
res_plugtest_validate,
res_plugtest_create1,
@ -95,29 +95,29 @@ PROCESS_THREAD(plugtest_server, ev, data)
PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE);
/* Initialize the REST engine. */
rest_init_engine();
coap_engine_init();
/* Activate the application-specific resources. */
rest_activate_resource(&res_plugtest_test, "test");
rest_activate_resource(&res_plugtest_validate, "validate");
rest_activate_resource(&res_plugtest_create1, "create1");
rest_activate_resource(&res_plugtest_create2, "create2");
rest_activate_resource(&res_plugtest_create3, "create3");
rest_activate_resource(&res_plugtest_longpath, "seg1/seg2/seg3");
rest_activate_resource(&res_plugtest_query, "query");
rest_activate_resource(&res_plugtest_locquery, "location-query");
rest_activate_resource(&res_plugtest_multi, "multi-format");
rest_activate_resource(&res_plugtest_link1, "link1");
rest_activate_resource(&res_plugtest_link2, "link2");
rest_activate_resource(&res_plugtest_link3, "link3");
rest_activate_resource(&res_plugtest_path, "path");
rest_activate_resource(&res_plugtest_separate, "separate");
rest_activate_resource(&res_plugtest_large, "large");
rest_activate_resource(&res_plugtest_large_update, "large-update");
rest_activate_resource(&res_plugtest_large_create, "large-create");
rest_activate_resource(&res_plugtest_obs, "obs");
coap_activate_resource(&res_plugtest_test, "test");
coap_activate_resource(&res_plugtest_validate, "validate");
coap_activate_resource(&res_plugtest_create1, "create1");
coap_activate_resource(&res_plugtest_create2, "create2");
coap_activate_resource(&res_plugtest_create3, "create3");
coap_activate_resource(&res_plugtest_longpath, "seg1/seg2/seg3");
coap_activate_resource(&res_plugtest_query, "query");
coap_activate_resource(&res_plugtest_locquery, "location-query");
coap_activate_resource(&res_plugtest_multi, "multi-format");
coap_activate_resource(&res_plugtest_link1, "link1");
coap_activate_resource(&res_plugtest_link2, "link2");
coap_activate_resource(&res_plugtest_link3, "link3");
coap_activate_resource(&res_plugtest_path, "path");
coap_activate_resource(&res_plugtest_separate, "separate");
coap_activate_resource(&res_plugtest_large, "large");
coap_activate_resource(&res_plugtest_large_update, "large-update");
coap_activate_resource(&res_plugtest_large_create, "large-create");
coap_activate_resource(&res_plugtest_obs, "obs");
rest_activate_resource(&res_mirror, "mirror");
coap_activate_resource(&res_mirror, "mirror");
/* Define application-specific events here. */
while(1) {

View File

@ -47,12 +47,8 @@
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#define PRINTLLADDR(addr)
#endif
/* double expansion */

View File

@ -36,43 +36,37 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#ifndef __PROJECT_ERBIUM_CONF_H__
#define __PROJECT_ERBIUM_CONF_H__
#ifndef PROJECT_ERBIUM_CONF_H_
#define PROJECT_ERBIUM_CONF_H_
/* Custom channel and PAN ID configuration for your project. */
/*
#define RF_CHANNEL 26
#define IEEE802154_CONF_PANID 0xABCD
*/
/* #define RF_CHANNEL 26 */
/* #define IEEE802154_CONF_PANID 0xABCD */
/* IP buffer size must match all other hops, in particular the border router. */
/*
#define UIP_CONF_BUFFER_SIZE 256
*/
/* #define UIP_CONF_BUFFER_SIZE 256 */
/* Increase rpl-border-router IP-buffer when using more than 64. */
#define REST_MAX_CHUNK_SIZE 48
#define COAP_MAX_CHUNK_SIZE 48
/* Estimate your header size, especially when using Proxy-Uri. */
/*
#define COAP_MAX_HEADER_SIZE 70
*/
/* #define COAP_MAX_HEADER_SIZE 70 */
/* Multiplies with chunk size, be aware of memory constraints. */
#ifndef COAP_MAX_OPEN_TRANSACTIONS
#define COAP_MAX_OPEN_TRANSACTIONS 4
#endif /* COAP_MAX_OPEN_TRANSACTIONS */
/* Must be <= open transactions, default is COAP_MAX_OPEN_TRANSACTIONS-1. */
/*
#define COAP_MAX_OBSERVERS 2
*/
/* #define COAP_MAX_OBSERVERS 2 */
/* Filtering .well-known/core per query can be disabled to save space. */
#define COAP_LINK_FORMAT_FILTERING 0
#define COAP_PROXY_OPTION_PROCESSING 0
/* Turn off DAO-ACK to make code smaller */
#define RPL_CONF_WITH_DAO_ACK 0
/* Enable client-side support for COAP observe */
#define COAP_OBSERVE_CLIENT 1
#endif /* __PROJECT_ERBIUM_CONF_H__ */
#ifndef COAP_OBSERVE_CLIENT
#define COAP_OBSERVE_CLIENT 1
#endif /* COAP_OBSERVE_CLIENT */
#endif /* PROJECT_ERBIUM_CONF_H_ */

View File

@ -37,12 +37,12 @@
*/
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "plugtest.h"
static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
RESOURCE(res_plugtest_create1,
"title=\"Creates on PUT\"",
@ -54,27 +54,27 @@ RESOURCE(res_plugtest_create1,
static uint8_t create1_exists = 0;
static void
res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
PRINTF("/create1 PUT");
if(coap_get_header_if_none_match(request)) {
if(!create1_exists) {
REST.set_response_status(response, REST.status.CREATED);
coap_set_status_code(response, CREATED_2_01);
create1_exists = 1;
} else {
REST.set_response_status(response, PRECONDITION_FAILED_4_12);
coap_set_status_code(response, PRECONDITION_FAILED_4_12);
}
} else {
REST.set_response_status(response, REST.status.CHANGED);
coap_set_status_code(response, CHANGED_2_04);
}
}
static void
res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
PRINTF("/create1 DELETE ");
REST.set_response_status(response, REST.status.DELETED);
coap_set_status_code(response, DELETED_2_02);
create1_exists = 0;
}

View File

@ -37,11 +37,11 @@
*/
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "plugtest.h"
static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
RESOURCE(res_plugtest_create2,
"title=\"Creates on POST\"",
@ -51,10 +51,10 @@ RESOURCE(res_plugtest_create2,
NULL);
static void
res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
PRINTF("/create2 ");
REST.set_response_status(response, REST.status.CREATED);
REST.set_header_location(response, "/location1/location2/location3");
coap_set_status_code(response, CREATED_2_01);
coap_set_header_location_path(response, "/location1/location2/location3");
}

View File

@ -37,12 +37,12 @@
*/
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "plugtest.h"
static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
RESOURCE(res_plugtest_create3,
"title=\"Default test resource\"",
@ -54,27 +54,27 @@ RESOURCE(res_plugtest_create3,
static uint8_t create3_exists = 0;
static void
res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
PRINTF("/create3 PUT ");
if(coap_get_header_if_none_match(request)) {
if(!create3_exists) {
REST.set_response_status(response, REST.status.CREATED);
coap_set_status_code(response, CREATED_2_01);
create3_exists = 1;
} else {
REST.set_response_status(response, PRECONDITION_FAILED_4_12);
coap_set_status_code(response, PRECONDITION_FAILED_4_12);
}
} else {
REST.set_response_status(response, REST.status.CHANGED);
coap_set_status_code(response, CHANGED_2_04);
}
}
static void
res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
PRINTF("/create3 DELETE ");
REST.set_response_status(response, REST.status.DELETED);
coap_set_status_code(response, DELETED_2_02);
create3_exists = 0;
}

View File

@ -37,11 +37,11 @@
*/
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "plugtest.h"
static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
/*
* Large resource that can be created using POST method
@ -54,38 +54,38 @@ RESOURCE(res_plugtest_large_create,
NULL);
static void
res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
coap_packet_t *const coap_req = (coap_packet_t *)request;
coap_message_t *const coap_req = (coap_message_t *)request;
uint8_t *incoming = NULL;
size_t len = 0;
unsigned int ct = -1;
if(!REST.get_header_content_type(request, &ct)) {
REST.set_response_status(response, REST.status.BAD_REQUEST);
if(!coap_get_header_content_format(request, &ct)) {
coap_set_status_code(response, BAD_REQUEST_4_00);
const char *error_msg = "NoContentType";
REST.set_response_payload(response, error_msg, strlen(error_msg));
coap_set_payload(response, error_msg, strlen(error_msg));
return;
}
if((len = REST.get_request_payload(request, (const uint8_t **)&incoming))) {
if((len = coap_get_payload(request, (const uint8_t **)&incoming))) {
if(coap_req->block1_num * coap_req->block1_size + len <= 2048) {
REST.set_response_status(response, REST.status.CREATED);
REST.set_header_location(response, "/nirvana");
coap_set_status_code(response, CREATED_2_01);
coap_set_header_location_path(response, "/nirvana");
coap_set_header_block1(response, coap_req->block1_num, 0,
coap_req->block1_size);
} else {
REST.set_response_status(response, REST.status.REQUEST_ENTITY_TOO_LARGE);
coap_set_status_code(response, REQUEST_ENTITY_TOO_LARGE_4_13);
const char *error_msg = "2048B max.";
REST.set_response_payload(response, error_msg, strlen(error_msg));
coap_set_payload(response, error_msg, strlen(error_msg));
return;
}
} else {
REST.set_response_status(response, REST.status.BAD_REQUEST);
coap_set_status_code(response, BAD_REQUEST_4_00);
const char *error_msg = "NoPayload";
REST.set_response_payload(response, error_msg, strlen(error_msg));
coap_set_payload(response, error_msg, strlen(error_msg));
return;
}
}

View File

@ -36,14 +36,15 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <stdio.h>
#include <string.h>
#include "sys/cc.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "plugtest.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
RESOURCE(
res_plugtest_large_update,
@ -58,21 +59,21 @@ static uint8_t large_update_store[MAX_PLUGFEST_BODY] = { 0 };
static unsigned int large_update_ct = APPLICATION_OCTET_STREAM;
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
/* Check the offset for boundaries of the resource data. */
if(*offset >= large_update_size) {
REST.set_response_status(response, REST.status.BAD_OPTION);
coap_set_status_code(response, BAD_OPTION_4_02);
/* A block error message should not exceed the minimum block size (16). */
const char *error_msg = "BlockOutOfScope";
REST.set_response_payload(response, error_msg, strlen(error_msg));
coap_set_payload(response, error_msg, strlen(error_msg));
return;
}
REST.set_response_payload(response, large_update_store + *offset,
coap_set_payload(response, large_update_store + *offset,
MIN(large_update_size - *offset, preferred_size));
REST.set_header_content_type(response, large_update_ct);
coap_set_header_content_format(response, large_update_ct);
/* IMPORTANT for chunk-wise resources: Signal chunk awareness to REST engine. */
*offset += preferred_size;
@ -83,22 +84,22 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
}
}
static void
res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
coap_packet_t *const coap_req = (coap_packet_t *)request;
coap_message_t *const coap_req = (coap_message_t *)request;
uint8_t *incoming = NULL;
size_t len = 0;
unsigned int ct = -1;
if(!REST.get_header_content_type(request, &ct)) {
REST.set_response_status(response, REST.status.BAD_REQUEST);
if(!coap_get_header_content_format(request, &ct)) {
coap_set_status_code(response, BAD_REQUEST_4_00);
const char *error_msg = "NoContentType";
REST.set_response_payload(response, error_msg, strlen(error_msg));
coap_set_payload(response, error_msg, strlen(error_msg));
return;
}
if((len = REST.get_request_payload(request, (const uint8_t **)&incoming))) {
if((len = coap_get_payload(request, (const uint8_t **)&incoming))) {
if(coap_req->block1_num * coap_req->block1_size + len <= sizeof(large_update_store)) {
memcpy(
large_update_store + coap_req->block1_num * coap_req->block1_size,
@ -106,13 +107,13 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
large_update_size = coap_req->block1_num * coap_req->block1_size + len;
large_update_ct = ct;
REST.set_response_status(response, REST.status.CHANGED);
coap_set_status_code(response, CHANGED_2_04);
coap_set_header_block1(response, coap_req->block1_num, 0,
coap_req->block1_size);
} else {
REST.set_response_status(response,
REST.status.REQUEST_ENTITY_TOO_LARGE);
REST.set_response_payload(
coap_set_status_code(response,
REQUEST_ENTITY_TOO_LARGE_4_13);
coap_set_payload(
response,
buffer,
snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "%uB max.",
@ -120,9 +121,9 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
return;
}
} else {
REST.set_response_status(response, REST.status.BAD_REQUEST);
coap_set_status_code(response, BAD_REQUEST_4_00);
const char *error_msg = "NoPayload";
REST.set_response_payload(response, error_msg, strlen(error_msg));
coap_set_payload(response, error_msg, strlen(error_msg));
return;
}
}

View File

@ -36,12 +36,13 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "plugtest.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
RESOURCE(res_plugtest_large,
"title=\"Large resource\";rt=\"block\";sz=\"" TO_STRING(CHUNKS_TOTAL) "\"",
@ -51,17 +52,17 @@ RESOURCE(res_plugtest_large,
NULL);
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
int32_t strpos = 0;
/* Check the offset for boundaries of the resource data. */
if(*offset >= CHUNKS_TOTAL) {
REST.set_response_status(response, REST.status.BAD_OPTION);
coap_set_status_code(response, BAD_OPTION_4_02);
/* A block error message should not exceed the minimum block size (16). */
const char *error_msg = "BlockOutOfScope";
REST.set_response_payload(response, error_msg, strlen(error_msg));
coap_set_payload(response, error_msg, strlen(error_msg));
return;
}
@ -79,8 +80,8 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
if(*offset + (int32_t)strpos > CHUNKS_TOTAL) {
strpos = CHUNKS_TOTAL - *offset;
}
REST.set_response_payload(response, buffer, strpos);
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
coap_set_payload(response, buffer, strpos);
coap_set_header_content_format(response, TEXT_PLAIN);
/* IMPORTANT for chunk-wise resources: Signal chunk awareness to REST engine. */
*offset += strpos;

View File

@ -37,11 +37,11 @@
*/
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "plugtest.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
RESOURCE(res_plugtest_link1,
"rt=\"Type1 Type2\";if=\"If1\"",
@ -63,9 +63,9 @@ RESOURCE(res_plugtest_link3,
NULL);
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const char *msg = "Dummy link";
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, msg, strlen(msg));
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, msg, strlen(msg));
}

View File

@ -37,11 +37,11 @@
*/
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "plugtest.h"
static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
RESOURCE(res_plugtest_locquery,
"title=\"Resource accepting query parameters\"",
@ -51,15 +51,15 @@ RESOURCE(res_plugtest_locquery,
NULL);
static void
res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
#if DEBUG
coap_packet_t *const coap_req = (coap_packet_t *)request;
coap_message_t *const coap_req = (coap_message_t *)request;
#endif
PRINTF(
"/location-query POST (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid);
REST.set_response_status(response, REST.status.CREATED);
REST.set_header_location(response, "?first=1&second=2");
coap_set_status_code(response, CREATED_2_01);
coap_set_header_location_query(response, "?first=1&second=2");
}

View File

@ -36,12 +36,14 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "plugtest.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
RESOURCE(res_plugtest_longpath,
"title=\"Long path resource\"",
@ -51,14 +53,14 @@ RESOURCE(res_plugtest_longpath,
NULL);
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
coap_packet_t *const coap_req = (coap_packet_t *)request;
coap_message_t *const coap_req = (coap_message_t *)request;
PRINTF("/seg1/seg2/seg3 GET ");
/* Code 2.05 CONTENT is default. */
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(
response,
buffer,
snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD,

View File

@ -36,12 +36,13 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "plugtest.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
RESOURCE(res_plugtest_multi,
"title=\"Resource providing text/plain and application/xml\";ct=\"0 41\"",
@ -51,27 +52,27 @@ RESOURCE(res_plugtest_multi,
NULL);
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
coap_packet_t *const coap_req = (coap_packet_t *)request;
coap_message_t *const coap_req = (coap_message_t *)request;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
coap_get_header_accept(request, &accept);
PRINTF("/multi-format GET (%s %u) ", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(
response,
buffer,
snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD,
"Type: %u\nCode: %u\nMID: %u%s", coap_req->type, coap_req->code,
coap_req->mid, accept != -1 ? "\nAccept: 0" : ""));
PRINTF("PLAIN\n");
} else if(accept == REST.type.APPLICATION_XML) {
REST.set_header_content_type(response, REST.type.APPLICATION_XML);
REST.set_response_payload(
} else if(accept == APPLICATION_XML) {
coap_set_header_content_format(response, APPLICATION_XML);
coap_set_payload(
response,
buffer,
snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD,
@ -79,9 +80,9 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
coap_req->type, coap_req->code, coap_req->mid, accept));
PRINTF("XML\n");
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
const char *msg = "Supporting content-types text/plain and application/xml";
REST.set_response_payload(response, msg, strlen(msg));
coap_set_payload(response, msg, strlen(msg));
PRINTF("ERROR\n");
}
}

View File

@ -36,15 +36,16 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "coap-observe.h"
#include "plugtest.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_periodic_handler(void);
PERIODIC_RESOURCE(res_plugtest_obs,
@ -67,35 +68,35 @@ static void
obs_purge_list()
{
PRINTF("### SERVER ACTION ### Purging obs list");
coap_remove_observer_by_uri(NULL, 0, res_plugtest_obs.url);
coap_remove_observer_by_uri(NULL, res_plugtest_obs.url);
}
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
/* Keep server log clean from ticking events */
if(request != NULL) {
PRINTF("/obs GET\n");
}
REST.set_header_content_type(response, obs_format);
REST.set_header_max_age(response, 5);
coap_set_header_content_format(response, obs_format);
coap_set_header_max_age(response, 5);
if(obs_content_len) {
REST.set_header_content_type(response, obs_format);
REST.set_response_payload(response, obs_content, obs_content_len);
coap_set_header_content_format(response, obs_format);
coap_set_payload(response, obs_content, obs_content_len);
} else {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, obs_content,
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, obs_content,
snprintf(obs_content, MAX_PLUGFEST_PAYLOAD, "TICK %lu", (unsigned long) obs_counter));
}
/* A post_handler that handles subscriptions will be called for periodic resources by the REST framework. */
/* A post_handler that handles subscriptions will be called for periodic resources by the CoAP framework. */
}
static void
res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
uint8_t *incoming = NULL;
unsigned int ct = -1;
REST.get_header_content_type(request, &ct);
coap_get_header_content_format(request, &ct);
PRINTF("/obs PUT\n");
@ -103,26 +104,26 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
obs_status = 1;
obs_format = ct;
} else {
obs_content_len = REST.get_request_payload(request,
obs_content_len = coap_get_payload(request,
(const uint8_t **)&incoming);
memcpy(obs_content, incoming, obs_content_len);
res_periodic_handler();
}
REST.set_response_status(response, REST.status.CHANGED);
coap_set_status_code(response, CHANGED_2_04);
}
static void
res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
PRINTF("/obs DELETE\n");
obs_status = 2;
REST.set_response_status(response, REST.status.DELETED);
coap_set_status_code(response, DELETED_2_02);
}
/*
* Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE.
* It will be called by the REST manager process with the defined period.
* It will be called by the CoAP manager process with the defined period.
*/
static void
res_periodic_handler()
@ -134,7 +135,7 @@ res_periodic_handler()
if(obs_status == 1) {
/* Notify the registered observers with the given message type, observe option, and payload. */
REST.notify_subscribers(&res_plugtest_obs);
coap_notify_observers(&res_plugtest_obs);
PRINTF("######### sending 5.00\n");
@ -142,7 +143,7 @@ res_periodic_handler()
} else if(obs_status == 2) {
/* Notify the registered observers with the given message type, observe option, and payload. */
REST.notify_subscribers(&res_plugtest_obs);
coap_notify_observers(&res_plugtest_obs);
obs_purge_list();
@ -150,6 +151,6 @@ res_periodic_handler()
obs_content_len = 0;
} else {
/* Notify the registered observers with the given message type, observe option, and payload. */
REST.notify_subscribers(&res_plugtest_obs);
coap_notify_observers(&res_plugtest_obs);
} obs_status = 0;
}

View File

@ -36,12 +36,13 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "plugtest.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
PARENT_RESOURCE(res_plugtest_path,
"title=\"Path test resource\";ct=\"40\"",
@ -51,22 +52,22 @@ PARENT_RESOURCE(res_plugtest_path,
NULL);
static void
res_get_handler(void *request, void *response, uint8_t *buffer,
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
const char *uri_path = NULL;
int len = REST.get_url(request, &uri_path);
int len = coap_get_header_uri_path(request, &uri_path);
int base_len = strlen(res_plugtest_path.url);
if(len == base_len) {
REST.set_header_content_type(response, REST.type.APPLICATION_LINK_FORMAT);
coap_set_header_content_format(response, APPLICATION_LINK_FORMAT);
snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD,
"</path/sub1>,</path/sub2>,</path/sub3>");
} else {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "/%.*s", len, uri_path);
}
REST.set_response_payload(response, buffer, strlen((char *)buffer));
coap_set_payload(response, buffer, strlen((char *)buffer));
}

View File

@ -36,12 +36,13 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "plugtest.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
RESOURCE(res_plugtest_query,
"title=\"Resource accepting query parameters\"",
@ -51,22 +52,22 @@ RESOURCE(res_plugtest_query,
NULL);
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
coap_packet_t *const coap_req = (coap_packet_t *)request;
coap_message_t *const coap_req = (coap_message_t *)request;
int len = 0;
const char *query = NULL;
PRINTF(
"/query GET (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid);
if((len = REST.get_query(request, &query))) {
if((len = coap_get_header_uri_query(request, &query))) {
PRINTF("Query: %.*s\n", len, query);
/* Code 2.05 CONTENT is default. */
}
REST.set_header_content_type(response,
REST.type.TEXT_PLAIN);
REST.set_response_payload(
coap_set_header_content_format(response,
TEXT_PLAIN);
coap_set_payload(
response,
buffer,
snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD,

View File

@ -36,14 +36,15 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "coap-transactions.h"
#include "coap-separate.h"
#include "plugtest.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_resume_handler(void);
PERIODIC_RESOURCE(res_plugtest_separate,
@ -67,9 +68,9 @@ static uint8_t separate_active = 0;
static application_separate_store_t separate_store[1];
void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
coap_packet_t *const coap_req = (coap_packet_t *)request;
coap_message_t *const coap_req = (coap_message_t *)request;
PRINTF("/separate ");
if(separate_active) {
@ -97,17 +98,16 @@ res_resume_handler()
PRINTF("/separate ");
coap_transaction_t *transaction = NULL;
if((transaction = coap_new_transaction(separate_store->request_metadata.mid,
&separate_store->request_metadata.addr,
separate_store->request_metadata.port))) {
&separate_store->request_metadata.endpoint))) {
PRINTF(
"RESPONSE (%s %u)\n", separate_store->request_metadata.type == COAP_TYPE_CON ? "CON" : "NON", separate_store->request_metadata.mid);
coap_packet_t response[1]; /* This way the packet can be treated as pointer as usual. */
coap_message_t response[1]; /* This way the message can be treated as pointer as usual. */
/* Restore the request information for the response. */
coap_separate_resume(response, &separate_store->request_metadata, CONTENT_2_05);
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, separate_store->buffer,
strlen(separate_store->buffer));
@ -120,8 +120,8 @@ res_resume_handler()
separate_store->request_metadata.block2_size);
/* Warning: No check for serialization error. */
transaction->packet_len = coap_serialize_message(response,
transaction->packet);
transaction->message_len = coap_serialize_message(response,
transaction->message);
coap_send_transaction(transaction);
/* The engine will clear the transaction (right after send for NON, after acked for CON). */

View File

@ -36,15 +36,17 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "plugtest.h"
#include "random.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
RESOURCE(res_plugtest_test, "title=\"Default test resource\"", res_get_handler, res_post_handler, res_put_handler, res_delete_handler);
@ -69,9 +71,9 @@ test_update_etag()
PRINTF("### SERVER ACTION ### Changed ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", test_etag_len, test_etag[0], test_etag[1], test_etag[2], test_etag[3], test_etag[4], test_etag[5], test_etag[6], test_etag[7]);
}
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
coap_packet_t *const coap_req = (coap_packet_t *)request;
coap_message_t *const coap_req = (coap_message_t *)request;
if(test_change) {
test_update_etag();
@ -82,48 +84,48 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
&& len == test_etag_len
&& memcmp(test_etag, bytes, len) == 0) {
PRINTF("validate ");
REST.set_response_status(response, REST.status.NOT_MODIFIED);
REST.set_header_etag(response, test_etag, test_etag_len);
coap_set_status_code(response, VALID_2_03);
coap_set_header_etag(response, test_etag, test_etag_len);
test_change = 1;
PRINTF("### SERVER ACTION ### Resource will change\n");
} else {
/* Code 2.05 CONTENT is default. */
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_header_etag(response, test_etag, test_etag_len);
REST.set_header_max_age(response, 30);
REST.set_response_payload(
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_header_etag(response, test_etag, test_etag_len);
coap_set_header_max_age(response, 30);
coap_set_payload(
response,
buffer,
snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "Type: %u\nCode: %u\nMID: %u", coap_req->type, coap_req->code, coap_req->mid));
}
}
static void
res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
#if DEBUG
coap_packet_t *const coap_req = (coap_packet_t *)request;
coap_message_t *const coap_req = (coap_message_t *)request;
PRINTF("/test POST (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid);
#endif
REST.set_response_status(response, REST.status.CREATED);
REST.set_header_location(response, "/location1/location2/location3");
coap_set_status_code(response, CREATED_2_01);
coap_set_header_location_path(response, "/location1/location2/location3");
}
static void
res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
#if DEBUG
coap_packet_t *const coap_req = (coap_packet_t *)request;
coap_message_t *const coap_req = (coap_message_t *)request;
PRINTF("/test PUT (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid);
#endif
if(coap_get_header_if_none_match(request)) {
if(test_none_match_okay) {
REST.set_response_status(response, REST.status.CREATED);
coap_set_status_code(response, CREATED_2_01);
test_none_match_okay = 0;
PRINTF("### SERVER ACTION ### If-None-Match will FAIL\n");
} else {
REST.set_response_status(response, PRECONDITION_FAILED_4_12);
coap_set_status_code(response, PRECONDITION_FAILED_4_12);
test_none_match_okay = 1;
PRINTF("### SERVER ACTION ### If-None-Match will SUCCEED\n");
@ -133,9 +135,9 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
&& memcmp(test_etag, bytes, len) == 0))
|| len == 0) {
test_update_etag();
REST.set_header_etag(response, test_etag, test_etag_len);
coap_set_header_etag(response, test_etag, test_etag_len);
REST.set_response_status(response, REST.status.CHANGED);
coap_set_status_code(response, CHANGED_2_04);
if(len > 0) {
test_change = 1;
@ -148,15 +150,15 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
test_etag[0], test_etag[1], test_etag[2], test_etag[3], test_etag[4], test_etag[5], test_etag[6], test_etag[7]);
REST.set_response_status(response, PRECONDITION_FAILED_4_12);
coap_set_status_code(response, PRECONDITION_FAILED_4_12);
}
}
static void
res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
#if DEBUG
coap_packet_t *const coap_req = (coap_packet_t *)request;
coap_message_t *const coap_req = (coap_message_t *)request;
PRINTF("/test DELETE (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid);
#endif
REST.set_response_status(response, REST.status.DELETED);
coap_set_status_code(response, DELETED_2_02);
}

View File

@ -36,13 +36,15 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "plugtest.h"
#include "random.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
RESOURCE(res_plugtest_validate,
"title=\"Validation test resource\"",
@ -72,9 +74,9 @@ validate_update_etag()
validate_etag_len, validate_etag[0], validate_etag[1], validate_etag[2], validate_etag[3], validate_etag[4], validate_etag[5], validate_etag[6], validate_etag[7]);
}
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
coap_packet_t *const coap_req = (coap_packet_t *)request;
coap_message_t *const coap_req = (coap_message_t *)request;
if(validate_change) {
validate_update_etag();
@ -85,17 +87,17 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
if((len = coap_get_header_etag(request, &bytes)) > 0
&& len == validate_etag_len && memcmp(validate_etag, bytes, len) == 0) {
PRINTF("validate ");
REST.set_response_status(response, REST.status.NOT_MODIFIED);
REST.set_header_etag(response, validate_etag, validate_etag_len);
coap_set_status_code(response, VALID_2_03);
coap_set_header_etag(response, validate_etag, validate_etag_len);
validate_change = 1;
PRINTF("### SERVER ACTION ### Resouce will change\n");
} else {
/* Code 2.05 CONTENT is default. */
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_header_etag(response, validate_etag, validate_etag_len);
REST.set_header_max_age(response, 30);
REST.set_response_payload(
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_header_etag(response, validate_etag, validate_etag_len);
coap_set_header_max_age(response, 30);
coap_set_payload(
response,
buffer,
snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD,
@ -104,10 +106,10 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
}
}
static void
res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
#if DEBUG
coap_packet_t *const coap_req = (coap_packet_t *)request;
coap_message_t *const coap_req = (coap_message_t *)request;
#endif
PRINTF("/validate PUT ");
@ -118,9 +120,9 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
&& memcmp(validate_etag, bytes, len) == 0))
|| len == 0) {
validate_update_etag();
REST.set_header_etag(response, validate_etag, validate_etag_len);
coap_set_header_etag(response, validate_etag, validate_etag_len);
REST.set_response_status(response, REST.status.CHANGED);
coap_set_status_code(response, CHANGED_2_04);
if(len > 0) {
validate_change = 1;
@ -134,6 +136,6 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
validate_etag[0], validate_etag[1], validate_etag[2], validate_etag[3], validate_etag[4], validate_etag[5], validate_etag[6], validate_etag[7]);
REST.set_response_status(response, PRECONDITION_FAILED_4_12);
coap_set_status_code(response, PRECONDITION_FAILED_4_12);
}
}

View File

@ -36,13 +36,14 @@
* Lars Schmertmann <SmallLars@t-online.de>
*/
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap-block1.h"
#include "coap-separate.h"
#include "coap-transactions.h"
static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
SEPARATE_RESOURCE(res_b1_sep_b2, "title=\"Block1 + Separate + Block2 demo\"", NULL, res_post_handler, NULL, NULL, NULL);
#define MAX_DATA_LEN 256
@ -52,7 +53,7 @@ static size_t big_msg_len = 0;
static coap_separate_t request_metadata;
static void
res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
/* Example allows only one request on time. There are no checks for multiply access !!! */
if(*offset == 0) {
@ -75,8 +76,8 @@ res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t prefer
/* Send first block */
coap_transaction_t *transaction = NULL;
if((transaction = coap_new_transaction(request_metadata.mid, &request_metadata.addr, request_metadata.port))) {
coap_packet_t resp[1]; /* This way the packet can be treated as pointer as usual. */
if((transaction = coap_new_transaction(request_metadata.mid, &request_metadata.endpoint))) {
coap_message_t resp[1]; /* This way the message can be treated as pointer as usual. */
/* Restore the request information for the response. */
coap_separate_resume(resp, &request_metadata, CONTENT_2_05);
@ -88,7 +89,7 @@ res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t prefer
}
/* Warning: No check for serialization error. */
transaction->packet_len = coap_serialize_message(resp, transaction->packet);
transaction->message_len = coap_serialize_message(resp, transaction->message);
coap_send_transaction(transaction);
}
} else {

View File

@ -41,10 +41,11 @@
#if PLATFORM_HAS_BATTERY
#include <string.h>
#include "rest-engine.h"
#include <stdio.h>
#include "coap-engine.h"
#include "dev/battery-sensor.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
/* A simple getter example. Returns the reading from light sensor with a simple etag */
RESOURCE(res_battery,
@ -55,27 +56,27 @@ RESOURCE(res_battery,
NULL);
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
int battery = battery_sensor.value(0);
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", battery);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", battery);
REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'battery':%d}", battery);
coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'battery':%d}", battery);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
const char *msg = "Supporting content-types text/plain and application/json";
REST.set_response_payload(response, msg, strlen(msg));
coap_set_payload(response, msg, strlen(msg));
}
}
#endif /* PLATFORM_HAS_BATTERY */

View File

@ -36,13 +36,14 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
/*
* For data larger than REST_MAX_CHUNK_SIZE (e.g., when stored in flash) resources must be aware of the buffer limitation
* For data larger than COAP_MAX_CHUNK_SIZE (e.g., when stored in flash) resources must be aware of the buffer limitation
* and split their responses by themselves. To transfer the complete resource through a TCP stream or CoAP's blockwise transfer,
* the byte offset where to continue is provided to the handler as int32_t pointer.
* These chunk-wise resources must set the offset value to its new position or -1 of the end is reached.
@ -58,17 +59,17 @@ RESOURCE(res_chunks,
#define CHUNKS_TOTAL 2050
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
int32_t strpos = 0;
/* Check the offset for boundaries of the resource data. */
if(*offset >= CHUNKS_TOTAL) {
REST.set_response_status(response, REST.status.BAD_OPTION);
coap_set_status_code(response, BAD_OPTION_4_02);
/* A block error message should not exceed the minimum block size (16). */
const char *error_msg = "BlockOutOfScope";
REST.set_response_payload(response, error_msg, strlen(error_msg));
coap_set_payload(response, error_msg, strlen(error_msg));
return;
}
@ -85,7 +86,7 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
if(*offset + (int32_t)strpos > CHUNKS_TOTAL) {
strpos = CHUNKS_TOTAL - *offset;
}
REST.set_response_payload(response, buffer, strpos);
coap_set_payload(response, buffer, strpos);
/* IMPORTANT for chunk-wise resources: Signal chunk awareness to REST engine. */
*offset += strpos;

View File

@ -36,8 +36,9 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#define DEBUG 0
@ -52,7 +53,7 @@
#define PRINTLLADDR(addr)
#endif
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_event_handler(void);
/*
@ -74,10 +75,10 @@ EVENT_RESOURCE(res_event,
static int32_t event_counter = 0;
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "EVENT %lu", (unsigned long) event_counter));
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, buffer, snprintf((char *)buffer, preferred_size, "EVENT %lu", (unsigned long) event_counter));
/* A post_handler that handles subscriptions/observing will be called for periodic resources by the framework. */
}
@ -96,6 +97,6 @@ res_event_handler(void)
PRINTF("TICK %u for /%s\n", event_counter, res_event.url);
/* Notify the registered observers which will trigger the res_get_handler to create the response. */
REST.notify_subscribers(&res_event);
coap_notify_observers(&res_event);
}
}

View File

@ -38,9 +38,9 @@
#include <stdlib.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
/*
* A handler function named [resource name]_handler must be implemented for each RESOURCE.
@ -56,7 +56,7 @@ RESOURCE(res_hello,
NULL);
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const char *len = NULL;
/* Some data that has the length up to REST_MAX_CHUNK_SIZE. For more, see the chunk resource. */
@ -64,7 +64,7 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
int length = 12; /* |<-------->| */
/* The query string can be retrieved by rest_get_query() or parsed for its key-value pairs. */
if(REST.get_query_variable(request, "len", &len)) {
if(coap_get_query_variable(request, "len", &len)) {
length = atoi(len);
if(length < 0) {
length = 0;
@ -75,7 +75,7 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
memcpy(buffer, message, length);
} else {
memcpy(buffer, message, length);
} REST.set_header_content_type(response, REST.type.TEXT_PLAIN); /* text/plain is the default, hence this option could be omitted. */
REST.set_header_etag(response, (uint8_t *)&length, 1);
REST.set_response_payload(response, buffer, length);
} coap_set_header_content_format(response, TEXT_PLAIN); /* text/plain is the default, hence this option could be omitted. */
coap_set_header_etag(response, (uint8_t *)&length, 1);
coap_set_payload(response, buffer, length);
}

View File

@ -39,9 +39,8 @@
#include "contiki.h"
#if PLATFORM_HAS_LEDS
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "dev/leds.h"
#define DEBUG 0
@ -56,9 +55,9 @@
#define PRINTLLADDR(addr)
#endif
static void res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_post_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
/*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/
/* A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated */
RESOURCE(res_leds,
"title=\"LEDs: ?color=r|g|b, POST/PUT mode=on|off\";rt=\"Control\"",
NULL,
@ -67,7 +66,7 @@ RESOURCE(res_leds,
NULL);
static void
res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_post_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
size_t len = 0;
const char *color = NULL;
@ -75,7 +74,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t pr
uint8_t led = 0;
int success = 1;
if((len = REST.get_query_variable(request, "color", &color))) {
if((len = coap_get_query_variable(request, "color", &color))) {
PRINTF("color %.*s\n", len, color);
if(strncmp(color, "r", len) == 0) {
@ -89,7 +88,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t pr
}
} else {
success = 0;
} if(success && (len = REST.get_post_variable(request, "mode", &mode))) {
} if(success && (len = coap_get_post_variable(request, "mode", &mode))) {
PRINTF("mode %s\n", mode);
if(strncmp(mode, "on", len) == 0) {
@ -102,7 +101,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t pr
} else {
success = 0;
} if(!success) {
REST.set_response_status(response, REST.status.BAD_REQUEST);
coap_set_status_code(response, BAD_REQUEST_4_00);
}
}
#endif /* PLATFORM_HAS_LEDS */

View File

@ -40,11 +40,12 @@
#if PLATFORM_HAS_LIGHT
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "dev/light-sensor.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
/* A simple getter example. Returns the reading from light sensor with a simple etag */
RESOURCE(res_light,
@ -55,33 +56,33 @@ RESOURCE(res_light,
NULL);
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
uint16_t light_photosynthetic = light_sensor.value(LIGHT_SENSOR_PHOTOSYNTHETIC);
uint16_t light_solar = light_sensor.value(LIGHT_SENSOR_TOTAL_SOLAR);
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%u;%u", light_photosynthetic, light_solar);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%u;%u", light_photosynthetic, light_solar);
REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_XML) {
REST.set_header_content_type(response, REST.type.APPLICATION_XML);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "<light photosynthetic=\"%u\" solar=\"%u\"/>", light_photosynthetic, light_solar);
coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_XML) {
coap_set_header_content_format(response, APPLICATION_XML);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "<light photosynthetic=\"%u\" solar=\"%u\"/>", light_photosynthetic, light_solar);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'light':{'photosynthetic':%u,'solar':%u}}", light_photosynthetic, light_solar);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'light':{'photosynthetic':%u,'solar':%u}}", light_photosynthetic, light_solar);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
const char *msg = "Supporting content-types text/plain, application/xml, and application/json";
REST.set_response_payload(response, msg, strlen(msg));
coap_set_payload(response, msg, strlen(msg));
}
}
#endif /* PLATFORM_HAS_LIGHT */

View File

@ -36,8 +36,9 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#define DEBUG 0
@ -52,7 +53,7 @@
#define PRINTLLADDR(addr)
#endif
static void res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_any_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
/* This resource mirrors the incoming request. It shows how to access the options and how to set them for the response. */
RESOURCE(res_mirror,
@ -63,7 +64,7 @@ RESOURCE(res_mirror,
res_any_handler);
static void
res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_any_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
/* The ETag and Token is copied to the header. */
uint8_t opaque[] = { 0x0A, 0xBC, 0xDE };
@ -89,28 +90,28 @@ res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
/* snprintf() counts the terminating '\0' to the size parameter.
* The additional byte is taken care of by allocating REST_MAX_CHUNK_SIZE+1 bytes in the REST framework.
* Add +1 to fill the complete buffer, as the payload does not need a terminating '\0'. */
if(REST.get_header_content_type(request, &content_format)) {
if(coap_get_header_content_format(request, &content_format)) {
strpos += snprintf((char *)buffer, REST_MAX_CHUNK_SIZE + 1, "CF %u\n", content_format);
}
if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_header_accept(request, &content_format))) {
if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_accept(request, &content_format))) {
strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "Ac %u\n", content_format);
/* Some getters such as for ETag or Location are omitted, as these options should not appear in a request.
* Max-Age might appear in HTTP requests or used for special purposes in CoAP. */
}
if(strpos <= REST_MAX_CHUNK_SIZE && REST.get_header_max_age(request, &longint)) {
if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_max_age(request, &longint)) {
strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "MA %lu\n", (unsigned long) longint);
/* For HTTP this is the Length option, for CoAP it is the Size option. */
}
if(strpos <= REST_MAX_CHUNK_SIZE && REST.get_header_length(request, &longint)) {
if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_size1(request, &longint)) {
strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "SZ %lu\n", (unsigned long) longint);
}
if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_header_host(request, &str))) {
if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_host(request, &str))) {
strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "UH %.*s\n", len, str);
}
if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_url(request, &str))) {
if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_path(request, &str))) {
strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "UP %.*s\n", len, str);
}
if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_query(request, &str))) {
if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_query(request, &str))) {
strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "UQ %.*s\n", len, str);
/* Undefined request options for debugging: actions not required for normal RESTful Web service. */
}
@ -121,7 +122,7 @@ res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "LQ %.*s\n", len, str);
/* CoAP-specific example: actions not required for normal RESTful Web service. */
}
coap_packet_t *const coap_pkt = (coap_packet_t *)request;
coap_message_t *const coap_pkt = (coap_message_t *)request;
if(strpos <= REST_MAX_CHUNK_SIZE && coap_pkt->token_len > 0) {
strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "To 0x");
@ -132,10 +133,10 @@ res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "\n");
}
if(strpos <= REST_MAX_CHUNK_SIZE && IS_OPTION(coap_pkt, COAP_OPTION_OBSERVE)) {
if(strpos <= REST_MAX_CHUNK_SIZE && coap_is_option(coap_pkt, COAP_OPTION_OBSERVE)) {
strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "Ob %lu\n", (unsigned long) coap_pkt->observe);
}
if(strpos <= REST_MAX_CHUNK_SIZE && IS_OPTION(coap_pkt, COAP_OPTION_ETAG)) {
if(strpos <= REST_MAX_CHUNK_SIZE && coap_is_option(coap_pkt, COAP_OPTION_ETAG)) {
strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "ET 0x");
int index = 0;
for(index = 0; index < coap_pkt->etag_len; ++index) {
@ -149,22 +150,22 @@ res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_block1(request, &block_num, &block_more, &block_size, NULL)) {
strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "B1 %lu%s (%u)\n", (unsigned long) block_num, block_more ? "+" : "", block_size);
}
if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_request_payload(request, &bytes))) {
if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_payload(request, &bytes))) {
strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "%.*s", len, bytes);
}
if(strpos >= REST_MAX_CHUNK_SIZE) {
buffer[REST_MAX_CHUNK_SIZE - 1] = 0xBB; /* '»' to indicate truncation */
}
REST.set_response_payload(response, buffer, strpos);
coap_set_payload(response, buffer, strpos);
PRINTF("/mirror options received: %s\n", buffer);
/* Set dummy header options for response. Like getters, some setters are not implemented for HTTP and have no effect. */
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_header_max_age(response, 17); /* For HTTP, browsers will not re-request the page for 17 seconds. */
REST.set_header_etag(response, opaque, 2);
REST.set_header_location(response, location); /* Initial slash is omitted by framework */
REST.set_header_length(response, strpos); /* For HTTP, browsers will not re-request the page for 10 seconds. CoAP action depends on the client. */
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_header_max_age(response, 17); /* For HTTP, browsers will not re-request the page for 17 seconds. */
coap_set_header_etag(response, opaque, 2);
coap_set_header_location_path(response, location); /* Initial slash is omitted by framework */
coap_set_header_size1(response, strpos); /* For HTTP, browsers will not re-request the page for 10 s. CoAP action depends on the client. */
/* CoAP-specific example: actions not required for normal RESTful Web service. */
coap_set_header_uri_host(response, "tiki");

View File

@ -36,11 +36,12 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_periodic_handler(void);
PERIODIC_RESOURCE(res_push,
@ -58,18 +59,18 @@ PERIODIC_RESOURCE(res_push,
static int32_t event_counter = 0;
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
/*
* For minimal complexity, request query and options should be ignored for GET on observable resources.
* Otherwise the requests must be stored with the observer list and passed by REST.notify_subscribers().
* Otherwise the requests must be stored with the observer list and passed by coap_notify_subscribers().
* This would be a TODO in the corresponding files in contiki/apps/erbium/!
*/
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_header_max_age(response, res_push.periodic->period / CLOCK_SECOND);
REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "VERY LONG EVENT %lu", (unsigned long) event_counter));
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_header_max_age(response, res_push.periodic->period / CLOCK_SECOND);
coap_set_payload(response, buffer, snprintf((char *)buffer, preferred_size, "VERY LONG EVENT %lu", (unsigned long) event_counter));
/* The REST.subscription_handler() will be called for observable resources by the REST framework. */
/* The coap_subscription_handler() will be called for observable resources by the REST framework. */
}
/*
* Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE.
@ -84,6 +85,6 @@ res_periodic_handler()
/* Usually a condition is defined under with subscribers are notified, e.g., large enough delta in sensor reading. */
if(1) {
/* Notify the registered observers which will trigger the res_get_handler to create the response. */
REST.notify_subscribers(&res_push);
coap_notify_observers(&res_push);
}
}

View File

@ -39,12 +39,12 @@
#include "contiki.h"
#if PLATFORM_HAS_RADIO
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "net/netstack.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
/* A simple getter example. Returns the reading of the rssi/lqi from radio sensor */
RESOURCE(res_radio,
@ -55,7 +55,7 @@ RESOURCE(res_radio,
NULL);
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
size_t len = 0;
const char *p = NULL;
@ -64,9 +64,9 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
int success = 0;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
coap_get_header_accept(request, &accept);
if((len = REST.get_query_variable(request, "p", &p))) {
if((len = coap_get_query_variable(request, "p", &p))) {
if(strncmp(p, "rssi", len) == 0) {
if(NETSTACK_RADIO.get_value(RADIO_PARAM_RSSI, &value) ==
RADIO_RESULT_OK) {
@ -77,23 +77,23 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
}
if(success) {
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", rssi);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", rssi);
REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'rssi':%d}", rssi);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'rssi':%d}", rssi);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
const char *msg = "Supporting content-types text/plain and application/json";
REST.set_response_payload(response, msg, strlen(msg));
coap_set_payload(response, msg, strlen(msg));
}
} else {
REST.set_response_status(response, REST.status.BAD_REQUEST);
coap_set_status_code(response, BAD_REQUEST_4_00);
}
}
#endif /* PLATFORM_HAS_RADIO */

View File

@ -37,11 +37,12 @@
*/
#include <string.h>
#include "rest-engine.h"
#include <stdio.h>
#include "coap-engine.h"
#include "coap-separate.h"
#include "coap-transactions.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_resume_handler(void);
SEPARATE_RESOURCE(res_separate,
@ -68,7 +69,7 @@ static uint8_t separate_active = 0;
static application_separate_store_t separate_store[COAP_MAX_OPEN_SEPARATE];
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
/*
* Example allows only one open separate response.
@ -96,11 +97,11 @@ res_resume_handler()
{
if(separate_active) {
coap_transaction_t *transaction = NULL;
if((transaction = coap_new_transaction(separate_store->request_metadata.mid, &separate_store->request_metadata.addr, separate_store->request_metadata.port))) {
coap_packet_t response[1]; /* This way the packet can be treated as pointer as usual. */
if((transaction = coap_new_transaction(separate_store->request_metadata.mid, &separate_store->request_metadata.endpoint))) {
coap_message_t response[1]; /* This way the message can be treated as pointer as usual. */
/* Restore the request information for the response. */
coap_separate_resume(response, &separate_store->request_metadata, REST.status.OK);
coap_separate_resume(response, &separate_store->request_metadata, CONTENT_2_05);
coap_set_payload(response, separate_store->buffer, strlen(separate_store->buffer));
@ -111,7 +112,7 @@ res_resume_handler()
coap_set_header_block2(response, separate_store->request_metadata.block2_num, 0, separate_store->request_metadata.block2_size);
/* Warning: No check for serialization error. */
transaction->packet_len = coap_serialize_message(response, transaction->packet);
transaction->message_len = coap_serialize_message(response, transaction->message);
coap_send_transaction(transaction);
/* The engine will clear the transaction (right after send for NON, after acked for CON). */

View File

@ -43,11 +43,12 @@
#if PLATFORM_HAS_SHT11
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "dev/sht11/sht11-sensor.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
/* Get Method Example. Returns the reading from temperature and humidity sensors. */
RESOURCE(res_sht11,
@ -58,7 +59,7 @@ RESOURCE(res_sht11,
NULL);
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
/* Temperature in Celsius (t in 14 bits resolution at 3 Volts)
* T = -39.60 + 0.01*t
@ -70,27 +71,27 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr
uint16_t rh = sht11_sensor.value(SHT11_SENSOR_HUMIDITY);
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%u;%u", temperature, rh);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%u;%u", temperature, rh);
REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_XML) {
REST.set_header_content_type(response, REST.type.APPLICATION_XML);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "<Temperature =\"%u\" Humidity=\"%u\"/>", temperature, rh);
coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_XML) {
coap_set_header_content_format(response, APPLICATION_XML);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "<Temperature =\"%u\" Humidity=\"%u\"/>", temperature, rh);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'Sht11':{'Temperature':%u,'Humidity':%u}}", temperature, rh);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'Sht11':{'Temperature':%u,'Humidity':%u}}", temperature, rh);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
const char *msg = "Supporting content-types text/plain, application/xml, and application/json";
REST.set_response_payload(response, msg, strlen(msg));
coap_set_payload(response, msg, strlen(msg));
}
}
#endif /* PLATFORM_HAS_SHT11 */

View File

@ -36,14 +36,15 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
/*
* Example for a resource that also handles all its sub-resources.
* Use REST.get_url() to multiplex the handling of the request depending on the Uri-Path.
* Use coap_get_url() to multiplex the handling of the request depending on the Uri-Path.
*/
PARENT_RESOURCE(res_sub,
"title=\"Sub-resource demo\"",
@ -53,17 +54,17 @@ PARENT_RESOURCE(res_sub,
NULL);
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
coap_set_header_content_format(response, TEXT_PLAIN);
const char *uri_path = NULL;
int len = REST.get_url(request, &uri_path);
int len = coap_get_header_uri_path(request, &uri_path);
int base_len = strlen(res_sub.url);
if(len == base_len) {
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "Request any sub-resource of /%s", res_sub.url);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "Request any sub-resource of /%s", res_sub.url);
} else {
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, ".%.*s", len - base_len, uri_path + base_len);
} REST.set_response_payload(response, buffer, strlen((char *)buffer));
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, ".%.*s", len - base_len, uri_path + base_len);
} coap_set_payload(response, buffer, strlen((char *)buffer));
}

View File

@ -44,11 +44,12 @@
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "rest-engine.h"
#include "coap-engine.h"
#include "dev/temperature-sensor.h"
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_periodic_handler(void);
#define MAX_AGE 60
@ -69,43 +70,43 @@ PERIODIC_RESOURCE(res_temperature,
res_periodic_handler);
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
/*
* For minimal complexity, request query and options should be ignored for GET on observable resources.
* Otherwise the requests must be stored with the observer list and passed by REST.notify_subscribers().
* Otherwise the requests must be stored with the observer list and passed by coap_notify_observers().
* This would be a TODO in the corresponding files in contiki/apps/erbium/!
*/
int temperature = temperature_sensor.value(0);
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", temperature);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", temperature);
REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'temperature':%d}", temperature);
coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'temperature':%d}", temperature);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
const char *msg = "Supporting content-types text/plain and application/json";
REST.set_response_payload(response, msg, strlen(msg));
coap_set_payload(response, msg, strlen(msg));
}
REST.set_header_max_age(response, MAX_AGE);
coap_set_header_max_age(response, MAX_AGE);
/* The REST.subscription_handler() will be called for observable resources by the REST framework. */
/* The coap_subscription_handler() will be called for observable resources by the coap_framework. */
}
/*
* Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE.
* It will be called by the REST manager process with the defined period.
* It will be called by the coap_manager process with the defined period.
*/
static void
res_periodic_handler()
@ -119,7 +120,7 @@ res_periodic_handler()
interval_counter = 0;
temperature_old = temperature;
/* Notify the registered observers which will trigger the res_get_handler to create the response. */
REST.notify_subscribers(&res_temperature);
coap_notify_observers(&res_temperature);
}
}
#endif /* PLATFORM_HAS_TEMPERATURE */

View File

@ -42,10 +42,10 @@
#include <string.h>
#include "contiki.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "dev/leds.h"
static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
/* A simple actuator example. Toggles the red led */
RESOURCE(res_toggle,
@ -56,7 +56,7 @@ RESOURCE(res_toggle,
NULL);
static void
res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
leds_toggle(LEDS_RED);
}

View File

@ -1,231 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<project EXPORT="discard">[APPS_DIR]/mrm</project>
<project EXPORT="discard">[APPS_DIR]/mspsim</project>
<project EXPORT="discard">[APPS_DIR]/avrora</project>
<project EXPORT="discard">[APPS_DIR]/serial_socket</project>
<project EXPORT="discard">[APPS_DIR]/collect-view</project>
<project EXPORT="discard">[APPS_DIR]/powertracker</project>
<simulation>
<title>REST with RPL router</title>
<speedlimit>1.0</speedlimit>
<randomseed>123456</randomseed>
<motedelay_us>1000000</motedelay_us>
<radiomedium>
org.contikios.cooja.radiomediums.UDGM
<transmitting_range>50.0</transmitting_range>
<interference_range>50.0</interference_range>
<success_ratio_tx>1.0</success_ratio_tx>
<success_ratio_rx>1.0</success_ratio_rx>
</radiomedium>
<events>
<logoutput>40000</logoutput>
</events>
<motetype>
org.contikios.cooja.mspmote.SkyMoteType
<identifier>slipradio</identifier>
<description>Sky SLIP radio</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/ipv6/slip-radio/slip-radio.c</source>
<commands EXPORT="discard">make slip-radio.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/ipv6/slip-radio/slip-radio.sky</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface>
</motetype>
<motetype>
org.contikios.cooja.mspmote.SkyMoteType
<identifier>server</identifier>
<description>Erbium Server</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/coap/coap-example-server.c</source>
<commands EXPORT="discard">make coap-example-server.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/coap/coap-example-server.sky</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface>
</motetype>
<motetype>
org.contikios.cooja.mspmote.SkyMoteType
<identifier>client</identifier>
<description>Erbium Client</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/coap/coap-example-client.c</source>
<commands EXPORT="discard">make coap-example-client.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/coap/coap-example-client.sky</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface>
</motetype>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>30.303994886410642</x>
<y>17.22128424003353</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>1</id>
</interface_config>
<motetype_identifier>slipradio</motetype_identifier>
</mote>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>46.57186415376375</x>
<y>37.25589203828498</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>2</id>
</interface_config>
<motetype_identifier>server</motetype_identifier>
</mote>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>18.194682268367348</x>
<y>50.210548118402656</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>3</id>
</interface_config>
<motetype_identifier>client</motetype_identifier>
</mote>
</simulation>
<plugin>
org.contikios.cooja.plugins.SimControl
<width>259</width>
<z>0</z>
<height>179</height>
<location_x>1</location_x>
<location_y>2</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Visualizer
<plugin_config>
<skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.AttributeVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.LEDVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.AddressVisualizerSkin</skin>
<viewport>2.255467003316979 0.0 0.0 2.255467003316979 59.30641698643764 -13.478401994502008</viewport>
</plugin_config>
<width>300</width>
<z>2</z>
<height>178</height>
<location_x>262</location_x>
<location_y>1</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.LogListener
<plugin_config>
<filter />
<formatted_time />
<coloring />
</plugin_config>
<width>762</width>
<z>4</z>
<height>491</height>
<location_x>2</location_x>
<location_y>182</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.RadioLogger
<plugin_config>
<split>150</split>
<formatted_time />
<showdups>false</showdups>
<hidenodests>false</hidenodests>
<analyzers name="6lowpan" />
</plugin_config>
<width>451</width>
<z>-1</z>
<height>305</height>
<location_x>73</location_x>
<location_y>140</location_y>
<minimized>true</minimized>
</plugin>
<plugin>
org.contikios.cooja.plugins.TimeLine
<plugin_config>
<mote>0</mote>
<mote>1</mote>
<mote>2</mote>
<showRadioRXTX />
<showRadioHW />
<showLEDs />
<showWatchpoints />
<zoomfactor>25.49079397896416</zoomfactor>
</plugin_config>
<width>1624</width>
<z>5</z>
<height>252</height>
<location_x>6</location_x>
<location_y>712</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.MoteInterfaceViewer
<mote_arg>1</mote_arg>
<plugin_config>
<interface>Serial port</interface>
<scrollpos>0,0</scrollpos>
</plugin_config>
<width>853</width>
<z>3</z>
<height>491</height>
<location_x>765</location_x>
<location_y>182</location_y>
</plugin>
<plugin>
org.contikios.cooja.serialsocket.SerialSocketServer
<mote_arg>0</mote_arg>
<width>422</width>
<z>1</z>
<height>82</height>
<location_x>606</location_x>
<location_y>51</location_y>
</plugin>
</simconf>

View File

@ -1,203 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<project EXPORT="discard">[APPS_DIR]/mrm</project>
<project EXPORT="discard">[APPS_DIR]/mspsim</project>
<project EXPORT="discard">[APPS_DIR]/avrora</project>
<project EXPORT="discard">[APPS_DIR]/serial_socket</project>
<project EXPORT="discard">[APPS_DIR]/collect-view</project>
<project EXPORT="discard">[APPS_DIR]/powertracker</project>
<simulation>
<title>REST with RPL router</title>
<speedlimit>1.0</speedlimit>
<randomseed>123456</randomseed>
<motedelay_us>1000000</motedelay_us>
<radiomedium>
org.contikios.cooja.radiomediums.UDGM
<transmitting_range>50.0</transmitting_range>
<interference_range>50.0</interference_range>
<success_ratio_tx>1.0</success_ratio_tx>
<success_ratio_rx>1.0</success_ratio_rx>
</radiomedium>
<events>
<logoutput>40000</logoutput>
</events>
<motetype>
org.contikios.cooja.mspmote.SkyMoteType
<identifier>rplroot</identifier>
<description>Sky RPL Root</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/rpl-border-router/border-router.c</source>
<commands EXPORT="discard">make border-router.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/rpl-border-router/border-router.sky</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface>
</motetype>
<motetype>
org.contikios.cooja.mspmote.SkyMoteType
<identifier>server</identifier>
<description>Erbium Server</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/coap/coap-example-server.c</source>
<commands EXPORT="discard">make coap-example-server.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/coap/coap-example-server.sky</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface>
</motetype>
<motetype>
org.contikios.cooja.mspmote.SkyMoteType
<identifier>client</identifier>
<description>Erbium Client</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/coap/coap-example-observe-client.c</source>
<commands EXPORT="discard">make coap-example-observe-client.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/coap/coap-example-observe-client.sky</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface>
</motetype>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>33.260163187353555</x>
<y>30.643217359962595</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>1</id>
</interface_config>
<motetype_identifier>rplroot</motetype_identifier>
</mote>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>54.537149936813485</x>
<y>51.51086225537906</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>2</id>
</interface_config>
<motetype_identifier>server</motetype_identifier>
</mote>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>77.97942851220571</x>
<y>67.86182390447284</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>3</id>
</interface_config>
<motetype_identifier>client</motetype_identifier>
</mote>
</simulation>
<plugin>
org.contikios.cooja.plugins.SimControl
<width>259</width>
<z>3</z>
<height>179</height>
<location_x>2</location_x>
<location_y>1</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Visualizer
<plugin_config>
<skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.AttributeVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.LEDVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.AddressVisualizerSkin</skin>
<viewport>2.092412892721766 0.0 0.0 2.092412892721766 34.70057915472623 -45.606066372444175</viewport>
</plugin_config>
<width>300</width>
<z>4</z>
<height>178</height>
<location_x>261</location_x>
<location_y>1</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.LogListener
<plugin_config>
<filter />
<formatted_time />
<coloring />
</plugin_config>
<width>762</width>
<z>0</z>
<height>491</height>
<location_x>2</location_x>
<location_y>182</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.RadioLogger
<plugin_config>
<split>167</split>
<formatted_time />
<showdups>false</showdups>
<hidenodests>false</hidenodests>
<analyzers name="6lowpan" />
</plugin_config>
<width>560</width>
<z>1</z>
<height>492</height>
<location_x>764</location_x>
<location_y>181</location_y>
</plugin>
<plugin>
org.contikios.cooja.serialsocket.SerialSocketServer
<mote_arg>0</mote_arg>
<plugin_config>
<port>60001</port>
<bound>true</bound>
</plugin_config>
<width>362</width>
<z>2</z>
<height>116</height>
<location_x>561</location_x>
<location_y>1</location_y>
</plugin>
</simconf>

View File

@ -1,231 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<project EXPORT="discard">[APPS_DIR]/mrm</project>
<project EXPORT="discard">[APPS_DIR]/mspsim</project>
<project EXPORT="discard">[APPS_DIR]/avrora</project>
<project EXPORT="discard">[APPS_DIR]/serial_socket</project>
<project EXPORT="discard">[APPS_DIR]/collect-view</project>
<project EXPORT="discard">[APPS_DIR]/powertracker</project>
<simulation>
<title>REST with RPL router</title>
<speedlimit>1.0</speedlimit>
<randomseed>123456</randomseed>
<motedelay_us>1000000</motedelay_us>
<radiomedium>
org.contikios.cooja.radiomediums.UDGM
<transmitting_range>50.0</transmitting_range>
<interference_range>50.0</interference_range>
<success_ratio_tx>1.0</success_ratio_tx>
<success_ratio_rx>1.0</success_ratio_rx>
</radiomedium>
<events>
<logoutput>40000</logoutput>
</events>
<motetype>
org.contikios.cooja.mspmote.SkyMoteType
<identifier>rplroot</identifier>
<description>Sky RPL Root</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/rpl-border-router/border-router.c</source>
<commands EXPORT="discard">make border-router.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/rpl-border-router/border-router.sky</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface>
</motetype>
<motetype>
org.contikios.cooja.mspmote.SkyMoteType
<identifier>server</identifier>
<description>Erbium Server</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/coap/coap-example-server.c</source>
<commands EXPORT="discard">make coap-example-server.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/coap/coap-example-server.sky</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface>
</motetype>
<motetype>
org.contikios.cooja.mspmote.SkyMoteType
<identifier>client</identifier>
<description>Erbium Client</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/coap/coap-example-client.c</source>
<commands EXPORT="discard">make coap-example-client.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/coap/coap-example-client.sky</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface>
</motetype>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>33.260163187353555</x>
<y>30.643217359962595</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>1</id>
</interface_config>
<motetype_identifier>rplroot</motetype_identifier>
</mote>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>46.57186415376375</x>
<y>40.35946215910942</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>2</id>
</interface_config>
<motetype_identifier>server</motetype_identifier>
</mote>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>18.638049428485125</x>
<y>47.55034515769599</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>3</id>
</interface_config>
<motetype_identifier>client</motetype_identifier>
</mote>
</simulation>
<plugin>
org.contikios.cooja.plugins.SimControl
<width>259</width>
<z>0</z>
<height>179</height>
<location_x>2</location_x>
<location_y>1</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Visualizer
<plugin_config>
<skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.AttributeVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.LEDVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.AddressVisualizerSkin</skin>
<viewport>3.61568947862321 0.0 0.0 3.61568947862321 15.610600779367 -85.92728269158351</viewport>
</plugin_config>
<width>300</width>
<z>2</z>
<height>178</height>
<location_x>261</location_x>
<location_y>1</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.LogListener
<plugin_config>
<filter />
<formatted_time />
<coloring />
</plugin_config>
<width>762</width>
<z>3</z>
<height>491</height>
<location_x>2</location_x>
<location_y>182</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.RadioLogger
<plugin_config>
<split>150</split>
<formatted_time />
<showdups>false</showdups>
<hidenodests>false</hidenodests>
<analyzers name="6lowpan" />
</plugin_config>
<width>451</width>
<z>-1</z>
<height>305</height>
<location_x>73</location_x>
<location_y>140</location_y>
<minimized>true</minimized>
</plugin>
<plugin>
org.contikios.cooja.serialsocket.SerialSocketServer
<mote_arg>0</mote_arg>
<width>422</width>
<z>4</z>
<height>74</height>
<location_x>578</location_x>
<location_y>18</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.TimeLine
<plugin_config>
<mote>0</mote>
<mote>1</mote>
<mote>2</mote>
<showRadioRXTX />
<showRadioHW />
<showLEDs />
<showWatchpoints />
<zoomfactor>25.49079397896416</zoomfactor>
</plugin_config>
<width>1624</width>
<z>5</z>
<height>252</height>
<location_x>6</location_x>
<location_y>712</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.MoteInterfaceViewer
<mote_arg>2</mote_arg>
<plugin_config>
<interface>Serial port</interface>
<scrollpos>0,0</scrollpos>
</plugin_config>
<width>853</width>
<z>1</z>
<height>491</height>
<location_x>765</location_x>
<location_y>182</location_y>
</plugin>
</simconf>

View File

@ -1,193 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<project EXPORT="discard">[APPS_DIR]/mrm</project>
<project EXPORT="discard">[APPS_DIR]/mspsim</project>
<project EXPORT="discard">[APPS_DIR]/avrora</project>
<project EXPORT="discard">[APPS_DIR]/serial_socket</project>
<project EXPORT="discard">[APPS_DIR]/collect-view</project>
<project EXPORT="discard">[APPS_DIR]/powertracker</project>
<simulation>
<title>REST with RPL router</title>
<speedlimit>1.0</speedlimit>
<randomseed>123456</randomseed>
<motedelay_us>1000000</motedelay_us>
<radiomedium>
org.contikios.cooja.radiomediums.UDGM
<transmitting_range>50.0</transmitting_range>
<interference_range>50.0</interference_range>
<success_ratio_tx>1.0</success_ratio_tx>
<success_ratio_rx>1.0</success_ratio_rx>
</radiomedium>
<events>
<logoutput>40000</logoutput>
</events>
<motetype>
org.contikios.cooja.mspmote.SkyMoteType
<identifier>rplroot</identifier>
<description>Sky RPL Root</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/rpl-border-router/border-router.c</source>
<commands EXPORT="discard">make border-router.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/rpl-border-router/border-router.sky</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface>
</motetype>
<motetype>
org.contikios.cooja.mspmote.SkyMoteType
<identifier>server</identifier>
<description>Erbium Server</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/coap/coap-example-server.c</source>
<commands EXPORT="discard">make coap-example-server.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/coap/coap-example-server.sky</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface>
</motetype>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>33.260163187353555</x>
<y>30.643217359962595</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>1</id>
</interface_config>
<motetype_identifier>rplroot</motetype_identifier>
</mote>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>35.100895239785295</x>
<y>39.70574552287428</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>2</id>
</interface_config>
<motetype_identifier>server</motetype_identifier>
</mote>
</simulation>
<plugin>
org.contikios.cooja.plugins.SimControl
<width>259</width>
<z>0</z>
<height>179</height>
<location_x>2</location_x>
<location_y>1</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Visualizer
<plugin_config>
<skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.AttributeVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.LEDVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.AddressVisualizerSkin</skin>
<viewport>7.9849281638410705 0.0 0.0 7.9849281638410705 -133.27812697619663 -225.04752569190535</viewport>
</plugin_config>
<width>300</width>
<z>1</z>
<height>175</height>
<location_x>262</location_x>
<location_y>2</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.LogListener
<plugin_config>
<filter />
<formatted_time />
<coloring />
</plugin_config>
<width>560</width>
<z>3</z>
<height>326</height>
<location_x>1</location_x>
<location_y>293</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.RadioLogger
<plugin_config>
<split>150</split>
<formatted_time />
<showdups>false</showdups>
<hidenodests>false</hidenodests>
<analyzers name="6lowpan" />
</plugin_config>
<width>451</width>
<z>-1</z>
<height>305</height>
<location_x>73</location_x>
<location_y>140</location_y>
<minimized>true</minimized>
</plugin>
<plugin>
org.contikios.cooja.serialsocket.SerialSocketServer
<mote_arg>0</mote_arg>
<width>422</width>
<z>4</z>
<height>74</height>
<location_x>39</location_x>
<location_y>199</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.TimeLine
<plugin_config>
<mote>0</mote>
<mote>1</mote>
<showRadioRXTX />
<showRadioHW />
<showLEDs />
<showWatchpoints />
<zoomfactor>25.49079397896416</zoomfactor>
</plugin_config>
<width>1624</width>
<z>5</z>
<height>252</height>
<location_x>4</location_x>
<location_y>622</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.MoteInterfaceViewer
<mote_arg>1</mote_arg>
<plugin_config>
<interface>Serial port</interface>
<scrollpos>0,0</scrollpos>
</plugin_config>
<width>702</width>
<z>2</z>
<height>646</height>
<location_x>564</location_x>
<location_y>2</location_y>
</plugin>
</simconf>

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2018, RISE SICS AB.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#error The CoAP example no longer fits the limited ROM in the Tmote Sky. \
Please select another platform with more ROM to compile the CoAP example.
/*---------------------------------------------------------------------------*/
#define COAP_OBSERVE_CLIENT 0
#define COAP_MAX_CHUNK_SIZE 48
/* Turn off DAO-ACK and probing to make code smaller */
#define RPL_CONF_WITH_DAO_ACK 0
#define LOG_CONF_LEVEL_MAIN 0
#define DCOSYNCH_CONF_ENABLED 0
#define PROCESS_CONF_NUMEVENTS 8
/*---------------------------------------------------------------------------*/

View File

@ -38,7 +38,13 @@
#include "contiki.h"
#include "services/lwm2m/lwm2m-engine.h"
#include "services/lwm2m/lwm2m-rd-client.h"
#include "services/lwm2m/lwm2m-device.h"
#include "services/lwm2m/lwm2m-server.h"
#include "services/lwm2m/lwm2m-security.h"
#include "services/ipso-objects/ipso-objects.h"
#include "services/ipso-objects/ipso-sensor-template.h"
#include "services/ipso-objects/ipso-control-template.h"
#define DEBUG DEBUG_NONE
#include "net/ipv6/uip-debug.h"
@ -52,9 +58,84 @@
#endif
#ifndef LWM2M_SERVER_ADDRESS
#define LWM2M_SERVER_ADDRESS "fd00::1"
#define LWM2M_SERVER_ADDRESS "coap://[fd00::1]"
#endif
#if BOARD_SENSORTAG
#include "board-peripherals.h"
/* Temperature reading */
static lwm2m_status_t
read_temp_value(const ipso_sensor_t *s, int32_t *value)
{
*value = 10 * hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_TEMP);
return LWM2M_STATUS_OK;
}
/* Humitidy reading */
static lwm2m_status_t
read_hum_value(const ipso_sensor_t *s, int32_t *value)
{
*value = 10 * hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_HUMIDITY);
return LWM2M_STATUS_OK;
}
/* Lux reading */
static lwm2m_status_t
read_lux_value(const ipso_sensor_t *s, int32_t *value)
{
*value = 10 * opt_3001_sensor.value(0);
return LWM2M_STATUS_OK;
}
/* Barometer reading */
static lwm2m_status_t
read_bar_value(const ipso_sensor_t *s, int32_t *value)
{
*value = 10 * bmp_280_sensor.value(BMP_280_SENSOR_TYPE_PRESS);
return LWM2M_STATUS_OK;
}
/* LED control */
static lwm2m_status_t
leds_set_val(ipso_control_t *control, uint8_t value)
{
if(value > 0) {
leds_on(LEDS_YELLOW);
} else {
leds_off(LEDS_YELLOW);
}
return LWM2M_STATUS_OK;
}
/*---------------------------------------------------------------------------*/
IPSO_CONTROL(led_control, 3311, 0, leds_set_val);
IPSO_SENSOR(temp_sensor, 3303, read_temp_value,
.max_range = 100000, /* 100 cel milli celcius */
.min_range = -10000, /* -10 cel milli celcius */
.unit = "Cel",
.update_interval = 30
);
IPSO_SENSOR(hum_sensor, 3304, read_hum_value,
.max_range = 100000, /* 100 % RH */
.min_range = 0,
.unit = "% RH",
.update_interval = 30
);
IPSO_SENSOR(lux_sensor, 3301, read_lux_value,
.max_range = 100000,
.min_range = -10000,
.unit = "LUX",
.update_interval = 30
);
IPSO_SENSOR(bar_sensor, 3315, read_bar_value,
.max_range = 100000, /* 100 cel milli celcius */
.min_range = -10000, /* -10 cel milli celcius */
.unit = "hPa",
.update_interval = 30
);
#endif /* BOARD_SENSORTAG */
PROCESS(example_ipso_objects, "IPSO object example");
AUTOSTART_PROCESSES(&example_ipso_objects);
/*---------------------------------------------------------------------------*/
@ -62,39 +143,70 @@ static void
setup_lwm2m_servers(void)
{
#ifdef LWM2M_SERVER_ADDRESS
uip_ipaddr_t addr;
if(uiplib_ipaddrconv(LWM2M_SERVER_ADDRESS, &addr)) {
lwm2m_engine_register_with_bootstrap_server(&addr, 0);
lwm2m_engine_register_with_server(&addr, 0);
coap_endpoint_t server_ep;
if(coap_endpoint_parse(LWM2M_SERVER_ADDRESS, strlen(LWM2M_SERVER_ADDRESS),
&server_ep) != 0) {
lwm2m_rd_client_register_with_bootstrap_server(&server_ep);
lwm2m_rd_client_register_with_server(&server_ep);
}
#endif /* LWM2M_SERVER_ADDRESS */
lwm2m_engine_use_bootstrap_server(REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER);
lwm2m_engine_use_registration_server(REGISTER_WITH_LWM2M_SERVER);
lwm2m_rd_client_use_bootstrap_server(REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER);
lwm2m_rd_client_use_registration_server(REGISTER_WITH_LWM2M_SERVER);
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(example_ipso_objects, ev, data)
{
static struct etimer periodic;
PROCESS_BEGIN();
PROCESS_PAUSE();
PRINTF("Starting IPSO objects example\n");
PRINTF("Starting IPSO objects example%s\n",
REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER ? " (bootstrap)" : "");
/* Initialize the OMA LWM2M engine */
lwm2m_engine_init();
/* Register default LWM2M objects */
lwm2m_engine_register_default_objects();
lwm2m_device_init();
lwm2m_security_init();
lwm2m_server_init();
/* Register default IPSO objects */
#if BOARD_SENSORTAG
ipso_sensor_add(&temp_sensor);
ipso_sensor_add(&hum_sensor);
ipso_sensor_add(&lux_sensor);
ipso_sensor_add(&bar_sensor);
ipso_control_add(&led_control);
ipso_button_init();
SENSORS_ACTIVATE(hdc_1000_sensor);
SENSORS_ACTIVATE(opt_3001_sensor);
SENSORS_ACTIVATE(bmp_280_sensor);
#else /* BOARD_SENSORTAG */
/* Register default IPSO objects - such as button..*/
ipso_objects_init();
#endif /* BOARD_SENSORTAG */
setup_lwm2m_servers();
/* Tick loop each 5 seconds */
etimer_set(&periodic, CLOCK_SECOND * 5);
while(1) {
PROCESS_WAIT_EVENT();
}
if(ev == PROCESS_EVENT_TIMER && etimer_expired(&periodic)) {
#if BOARD_SENSORTAG
/* deactive / activate to do a new reading */
SENSORS_DEACTIVATE(hdc_1000_sensor);
SENSORS_DEACTIVATE(opt_3001_sensor);
SENSORS_DEACTIVATE(bmp_280_sensor);
SENSORS_ACTIVATE(hdc_1000_sensor);
SENSORS_ACTIVATE(opt_3001_sensor);
SENSORS_ACTIVATE(bmp_280_sensor);
#endif /* BOARD_SENSORTAG */
etimer_reset(&periodic);
}
}
PROCESS_END();
}

View File

@ -44,7 +44,7 @@
#include "coap-constants.h"
#include "coap-engine.h"
#include "lwm2m-engine.h"
#include "oma-tlv.h"
#include "lwm2m-tlv.h"
#include "dev/serial-line.h"
#include "serial-protocol.h"
@ -187,13 +187,13 @@ client_chunk_handler(void *response)
} else {
/* otherwise update the current value */
if(format == LWM2M_TLV) {
oma_tlv_t tlv;
lwm2m_tlv_t tlv;
/* we can only read int32 for now ? */
if(oma_tlv_read(&tlv, chunk, len) > 0) {
if(lwm2m_tlv_read(&tlv, chunk, len) > 0) {
/* printf("TLV.type=%d len=%d id=%d value[0]=%d\n", */
/* tlv.type, tlv.length, tlv.id, tlv.value[0]); */
int value = oma_tlv_get_int32(&tlv);
int value = lwm2m_tlv_get_int32(&tlv);
snprintf(current_value, sizeof(current_value), "%d", value);
}
} else {
@ -257,8 +257,8 @@ setup_network(void)
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(router_process, ev, data)
{
/* This way the packet can be treated as pointer as usual. */
static coap_packet_t request[1];
/* This way the message can be treated as pointer as usual. */
static coap_message_t request[1];
static struct etimer timer;
uip_ds6_route_t *r;
uip_ipaddr_t *nexthop;
@ -269,7 +269,7 @@ PROCESS_THREAD(router_process, ev, data)
PROCESS_PAUSE();
/* receives all CoAP messages */
coap_init_engine();
coap_engine_init();
setup_network();

View File

@ -30,6 +30,9 @@
#ifndef PROJECT_CONF_H_
#define PROJECT_CONF_H_
/* No sleep on CC2538 to enable full 32 KiB RAM */
#define LPM_CONF_ENABLE 0
#ifdef BOARD_STRING
#define LWM2M_DEVICE_MODEL_NUMBER BOARD_STRING
#elif defined(CONTIKI_TARGET_WISMOTE)
@ -40,10 +43,14 @@
#define PLATFORM_REBOOT watchdog_reboot
#endif
#if BOARD_SENSORTAG
/* Real sensor is present... */
#else
#define IPSO_TEMPERATURE example_ipso_temperature
#endif /* BOARD_SENSORTAG */
/* Increase rpl-border-router IP-buffer when using more than 64. */
#define REST_MAX_CHUNK_SIZE 64
#define COAP_MAX_CHUNK_SIZE 64
/* Multiplies with chunk size, be aware of memory constraints. */
#define COAP_MAX_OPEN_TRANSACTIONS 4

View File

@ -45,6 +45,8 @@
#define LOG_CONF_LEVEL_TCPIP LOG_LEVEL_DBG
#define LOG_CONF_LEVEL_MAC LOG_LEVEL_DBG
#define LOG_CONF_LEVEL_FRAMER LOG_LEVEL_DBG
#define LOG_CONF_LEVEL_COAP LOG_LEVEL_DBG
#define LOG_CONF_LEVEL_LWM2M LOG_LEVEL_DBG
#define LOG_CONF_LEVEL_6TOP LOG_LEVEL_DBG
/* Enable cooja annotations */

View File

@ -39,7 +39,7 @@
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "contiki-net.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "board-peripherals.h"
#include "lib/sensors.h"
#include "lib/list.h"

View File

@ -37,7 +37,7 @@
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "contiki-net.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "board-peripherals.h"
#include "rf-core/rf-ble.h"
#include "cc26xx-web-demo.h"
@ -47,48 +47,48 @@
#include <string.h>
/*---------------------------------------------------------------------------*/
/* Common resources */
extern resource_t res_leds;
extern coap_resource_t res_leds;
extern resource_t res_batmon_temp;
extern resource_t res_batmon_volt;
extern coap_resource_t res_batmon_temp;
extern coap_resource_t res_batmon_volt;
extern resource_t res_device_sw;
extern resource_t res_device_hw;
extern resource_t res_device_uptime;
extern resource_t res_device_cfg_reset;
extern coap_resource_t res_device_sw;
extern coap_resource_t res_device_hw;
extern coap_resource_t res_device_uptime;
extern coap_resource_t res_device_cfg_reset;
extern resource_t res_parent_rssi;
extern resource_t res_parent_ip;
extern coap_resource_t res_parent_rssi;
extern coap_resource_t res_parent_ip;
#if RF_BLE_ENABLED
extern resource_t res_ble_advd;
extern coap_resource_t res_ble_advd;
#endif
extern resource_t res_toggle_red;
extern resource_t res_toggle_green;
extern coap_resource_t res_toggle_red;
extern coap_resource_t res_toggle_green;
/* Board-specific resources */
#if BOARD_SENSORTAG
extern resource_t res_bmp280_temp;
extern resource_t res_bmp280_press;
extern resource_t res_tmp007_amb;
extern resource_t res_tmp007_obj;
extern resource_t res_hdc1000_temp;
extern resource_t res_hdc1000_hum;
extern resource_t res_opt3001_light;
extern resource_t res_mpu_acc_x;
extern resource_t res_mpu_acc_y;
extern resource_t res_mpu_acc_z;
extern resource_t res_mpu_gyro_x;
extern resource_t res_mpu_gyro_y;
extern resource_t res_mpu_gyro_z;
extern coap_resource_t res_bmp280_temp;
extern coap_resource_t res_bmp280_press;
extern coap_resource_t res_tmp007_amb;
extern coap_resource_t res_tmp007_obj;
extern coap_resource_t res_hdc1000_temp;
extern coap_resource_t res_hdc1000_hum;
extern coap_resource_t res_opt3001_light;
extern coap_resource_t res_mpu_acc_x;
extern coap_resource_t res_mpu_acc_y;
extern coap_resource_t res_mpu_acc_z;
extern coap_resource_t res_mpu_gyro_x;
extern coap_resource_t res_mpu_gyro_y;
extern coap_resource_t res_mpu_gyro_z;
#else
extern resource_t res_toggle_orange;
extern resource_t res_toggle_yellow;
extern coap_resource_t res_toggle_orange;
extern coap_resource_t res_toggle_yellow;
#endif
#if CC26XX_WEB_DEMO_ADC_DEMO
extern resource_t res_adc_dio23;
extern coap_resource_t res_adc_dio23;
#endif
/*---------------------------------------------------------------------------*/
const char *coap_server_not_found_msg = "Resource not found";
@ -101,27 +101,27 @@ static void
start_board_resources(void)
{
rest_activate_resource(&res_toggle_green, "lt/g");
rest_activate_resource(&res_toggle_red, "lt/r");
rest_activate_resource(&res_leds, "lt");
coap_activate_resource(&res_toggle_green, "lt/g");
coap_activate_resource(&res_toggle_red, "lt/r");
coap_activate_resource(&res_leds, "lt");
#if BOARD_SENSORTAG
rest_activate_resource(&res_bmp280_temp, "sen/bar/temp");
rest_activate_resource(&res_bmp280_press, "sen/bar/pres");
rest_activate_resource(&res_tmp007_amb, "sen/tmp/amb");
rest_activate_resource(&res_tmp007_obj, "sen/tmp/obj");
rest_activate_resource(&res_hdc1000_temp, "sen/hdc/t");
rest_activate_resource(&res_hdc1000_hum, "sen/hdc/h");
rest_activate_resource(&res_opt3001_light, "sen/opt/light");
rest_activate_resource(&res_mpu_acc_x, "sen/mpu/acc/x");
rest_activate_resource(&res_mpu_acc_y, "sen/mpu/acc/y");
rest_activate_resource(&res_mpu_acc_z, "sen/mpu/acc/z");
rest_activate_resource(&res_mpu_gyro_x, "sen/mpu/gyro/x");
rest_activate_resource(&res_mpu_gyro_y, "sen/mpu/gyro/y");
rest_activate_resource(&res_mpu_gyro_z, "sen/mpu/gyro/z");
coap_activate_resource(&res_bmp280_temp, "sen/bar/temp");
coap_activate_resource(&res_bmp280_press, "sen/bar/pres");
coap_activate_resource(&res_tmp007_amb, "sen/tmp/amb");
coap_activate_resource(&res_tmp007_obj, "sen/tmp/obj");
coap_activate_resource(&res_hdc1000_temp, "sen/hdc/t");
coap_activate_resource(&res_hdc1000_hum, "sen/hdc/h");
coap_activate_resource(&res_opt3001_light, "sen/opt/light");
coap_activate_resource(&res_mpu_acc_x, "sen/mpu/acc/x");
coap_activate_resource(&res_mpu_acc_y, "sen/mpu/acc/y");
coap_activate_resource(&res_mpu_acc_z, "sen/mpu/acc/z");
coap_activate_resource(&res_mpu_gyro_x, "sen/mpu/gyro/x");
coap_activate_resource(&res_mpu_gyro_y, "sen/mpu/gyro/y");
coap_activate_resource(&res_mpu_gyro_z, "sen/mpu/gyro/z");
#elif BOARD_SMARTRF06EB
rest_activate_resource(&res_toggle_yellow, "lt/y");
rest_activate_resource(&res_toggle_orange, "lt/o");
coap_activate_resource(&res_toggle_yellow, "lt/y");
coap_activate_resource(&res_toggle_orange, "lt/o");
#endif
}
/*---------------------------------------------------------------------------*/
@ -134,25 +134,25 @@ PROCESS_THREAD(coap_server_process, ev, data)
printf("CC26XX CoAP Server\n");
/* Initialize the REST engine. */
rest_init_engine();
coap_engine_init();
rest_activate_resource(&res_batmon_temp, "sen/batmon/temp");
rest_activate_resource(&res_batmon_volt, "sen/batmon/voltage");
coap_activate_resource(&res_batmon_temp, "sen/batmon/temp");
coap_activate_resource(&res_batmon_volt, "sen/batmon/voltage");
#if CC26XX_WEB_DEMO_ADC_DEMO
rest_activate_resource(&res_adc_dio23, "sen/adc/dio23");
coap_activate_resource(&res_adc_dio23, "sen/adc/dio23");
#endif
rest_activate_resource(&res_device_hw, "dev/mdl/hw");
rest_activate_resource(&res_device_sw, "dev/mdl/sw");
rest_activate_resource(&res_device_uptime, "dev/uptime");
rest_activate_resource(&res_device_cfg_reset, "dev/cfg_reset");
coap_activate_resource(&res_device_hw, "dev/mdl/hw");
coap_activate_resource(&res_device_sw, "dev/mdl/sw");
coap_activate_resource(&res_device_uptime, "dev/uptime");
coap_activate_resource(&res_device_cfg_reset, "dev/cfg_reset");
rest_activate_resource(&res_parent_rssi, "net/parent/RSSI");
rest_activate_resource(&res_parent_ip, "net/parent/IPv6");
coap_activate_resource(&res_parent_rssi, "net/parent/RSSI");
coap_activate_resource(&res_parent_ip, "net/parent/IPv6");
#if RF_BLE_ENABLED
rest_activate_resource(&res_ble_advd, "dev/ble_advd");
coap_activate_resource(&res_ble_advd, "dev/ble_advd");
#endif
start_board_resources();

View File

@ -36,7 +36,7 @@
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "rf-core/rf-ble.h"
@ -49,7 +49,8 @@ const char *forbidden_payload = "Name to advertise unspecified.\n"
"Use name=<name> in the request";
/*---------------------------------------------------------------------------*/
static void
res_ble_post_put_handler(void *request, void *response, uint8_t *buffer,
res_ble_post_put_handler(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
size_t len = 0;
@ -60,7 +61,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer,
memset(name, 0, BLE_NAME_BUF_LEN);
len = REST.get_post_variable(request, "name", &text);
len = coap_get_post_variable(request, "name", &text);
if(len > 0 && len < BLE_NAME_BUF_LEN) {
memcpy(name, text, len);
@ -68,7 +69,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer,
success = 1;
}
len = REST.get_post_variable(request, "interval", &text);
len = coap_get_post_variable(request, "interval", &text);
rv = atoi(text);
@ -77,15 +78,15 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer,
success = 1;
}
len = REST.get_post_variable(request, "mode", &text);
len = coap_get_post_variable(request, "mode", &text);
if(len) {
if(strncmp(text, "on", len) == 0) {
if(rf_ble_beacond_start()) {
success = 1;
} else {
REST.set_response_status(response, REST.status.FORBIDDEN);
REST.set_response_payload(response, forbidden_payload,
coap_set_status_code(response, FORBIDDEN_4_03);
coap_set_payload(response, forbidden_payload,
strlen(forbidden_payload));
return;
}
@ -98,7 +99,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer,
}
if(!success) {
REST.set_response_status(response, REST.status.BAD_REQUEST);
coap_set_status_code(response, BAD_REQUEST_4_00);
}
}
/*---------------------------------------------------------------------------*/

View File

@ -37,7 +37,7 @@
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "sys/clock.h"
#include "coap-server.h"
@ -46,6 +46,7 @@
#include "ti-lib.h"
#include <string.h>
#include <stdio.h>
/*---------------------------------------------------------------------------*/
static uint16_t
detect_chip(void)
@ -74,106 +75,110 @@ detect_chip(void)
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_hw(void *request, void *response, uint8_t *buffer,
res_get_handler_hw(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
uint16_t chip = detect_chip();
REST.get_header_accept(request, &accept);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s on CC%u", BOARD_STRING,
chip);
REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"HW Ver\":\"%s on CC%u\"}",
BOARD_STRING, chip);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_XML) {
REST.set_header_content_type(response, REST.type.APPLICATION_XML);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_XML) {
coap_set_header_content_format(response, APPLICATION_XML);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
"<hw-ver val=\"%s on CC%u\"/>", BOARD_STRING,
chip);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
REST.set_response_payload(response, coap_server_supported_msg,
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, coap_server_supported_msg,
strlen(coap_server_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_sw(void *request, void *response, uint8_t *buffer,
res_get_handler_sw(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", CONTIKI_VERSION_STRING);
REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"SW Ver\":\"%s\"}",
CONTIKI_VERSION_STRING);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_XML) {
REST.set_header_content_type(response, REST.type.APPLICATION_XML);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_XML) {
coap_set_header_content_format(response, APPLICATION_XML);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
"<sw-ver val=\"%s\"/>", CONTIKI_VERSION_STRING);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
REST.set_response_payload(response, coap_server_supported_msg,
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, coap_server_supported_msg,
strlen(coap_server_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_uptime(void *request, void *response, uint8_t *buffer,
res_get_handler_uptime(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%lu", clock_seconds());
REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"uptime\":%lu}",
clock_seconds());
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_XML) {
REST.set_header_content_type(response, REST.type.APPLICATION_XML);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_XML) {
coap_set_header_content_format(response, APPLICATION_XML);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
"<uptime val=\"%lu\" unit=\"sec\"/>", clock_seconds());
REST.set_response_payload(response, buffer, strlen((char *)buffer));
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
REST.set_response_payload(response, coap_server_supported_msg,
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, coap_server_supported_msg,
strlen(coap_server_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
static void
res_post_handler_cfg_reset(void *request, void *response, uint8_t *buffer,
res_post_handler_cfg_reset(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
cc26xx_web_demo_restore_defaults();

View File

@ -40,13 +40,14 @@
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "dev/leds.h"
#include <string.h>
/*---------------------------------------------------------------------------*/
static void
res_post_put_handler(void *request, void *response, uint8_t *buffer,
res_post_put_handler(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
size_t len = 0;
@ -55,7 +56,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer,
uint8_t led = 0;
int success = 1;
if((len = REST.get_query_variable(request, "color", &color))) {
if((len = coap_get_query_variable(request, "color", &color))) {
if(strncmp(color, "r", len) == 0) {
led = LEDS_RED;
} else if(strncmp(color, "g", len) == 0) {
@ -73,7 +74,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer,
success = 0;
}
if(success && (len = REST.get_post_variable(request, "mode", &mode))) {
if(success && (len = coap_get_post_variable(request, "mode", &mode))) {
if(strncmp(mode, "on", len) == 0) {
leds_on(led);
} else if(strncmp(mode, "off", len) == 0) {
@ -86,7 +87,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer,
}
if(!success) {
REST.set_response_status(response, REST.status.BAD_REQUEST);
coap_set_status_code(response, BAD_REQUEST_4_00);
}
}
/*---------------------------------------------------------------------------*/

View File

@ -37,82 +37,86 @@
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "net/ipv6/uip-ds6.h"
#include "coap-server.h"
#include "cc26xx-web-demo.h"
#include "ti-lib.h"
#include <string.h>
#include <stdio.h>
/*---------------------------------------------------------------------------*/
extern int def_rt_rssi;
/*---------------------------------------------------------------------------*/
static void
res_get_handler_parent_rssi(void *request, void *response, uint8_t *buffer,
res_get_handler_parent_rssi(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", def_rt_rssi);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", def_rt_rssi);
REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"Parent RSSI\":\"%d\"}",
coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"Parent RSSI\":\"%d\"}",
def_rt_rssi);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_XML) {
REST.set_header_content_type(response, REST.type.APPLICATION_XML);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_XML) {
coap_set_header_content_format(response, APPLICATION_XML);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE,
"<parent-rssi val=\"%d\"/>", def_rt_rssi);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
REST.set_response_payload(response, coap_server_supported_msg,
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, coap_server_supported_msg,
strlen(coap_server_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_pref_parent(void *request, void *response, uint8_t *buffer,
res_get_handler_pref_parent(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
char def_rt_str[64];
REST.get_header_accept(request, &accept);
coap_get_header_accept(request, &accept);
memset(def_rt_str, 0, sizeof(def_rt_str));
cc26xx_web_demo_ipaddr_sprintf(def_rt_str, sizeof(def_rt_str),
uip_ds6_defrt_choose());
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", def_rt_str);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%s", def_rt_str);
REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"Parent\":\"%s\"}",
coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"Parent\":\"%s\"}",
def_rt_str);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_XML) {
REST.set_header_content_type(response, REST.type.APPLICATION_XML);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_XML) {
coap_set_header_content_format(response, APPLICATION_XML);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE,
"<parent=\"%s\"/>", def_rt_str);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
REST.set_response_payload(response, coap_server_supported_msg,
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, coap_server_supported_msg,
strlen(coap_server_supported_msg));
}
}

View File

@ -37,7 +37,7 @@
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "cc26xx-web-demo.h"
#include "coap-server.h"
@ -51,7 +51,8 @@
* called by all handlers and populates the CoAP response
*/
static void
res_get_handler_all(int sens_type, void *request, void *response,
res_get_handler_all(int sens_type, coap_message_t *request,
coap_message_t *response,
uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
@ -60,43 +61,44 @@ res_get_handler_all(int sens_type, void *request, void *response,
reading = cc26xx_web_demo_sensor_lookup(sens_type);
if(reading == NULL) {
REST.set_response_status(response, REST.status.NOT_FOUND);
REST.set_response_payload(response, coap_server_not_found_msg,
coap_set_status_code(response, NOT_FOUND_4_04);
coap_set_payload(response, coap_server_not_found_msg,
strlen(coap_server_not_found_msg));
return;
}
REST.get_header_accept(request, &accept);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", reading->converted);
REST.set_response_payload(response, (uint8_t *)buffer,
coap_set_payload(response, (uint8_t *)buffer,
strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"%s\":%s}",
reading->descr, reading->converted);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_XML) {
REST.set_header_content_type(response, REST.type.APPLICATION_XML);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_XML) {
coap_set_header_content_format(response, APPLICATION_XML);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
"<%s val=\"%s\" unit=\"%s\"/>", reading->xml_element,
reading->converted, reading->units);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
REST.set_response_payload(response, coap_server_supported_msg,
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, coap_server_supported_msg,
strlen(coap_server_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
/* BatMon resources and handler: Temperature, Voltage */
static void
res_get_handler_batmon_temp(void *request, void *response, uint8_t *buffer,
res_get_handler_batmon_temp(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BATMON_TEMP, request, response,
@ -104,7 +106,8 @@ res_get_handler_batmon_temp(void *request, void *response, uint8_t *buffer,
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_batmon_volt(void *request, void *response, uint8_t *buffer,
res_get_handler_batmon_volt(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BATMON_VOLT, request, response,
@ -120,7 +123,8 @@ RESOURCE(res_batmon_volt, "title=\"Battery Voltage\";rt=\"mV\"",
#if CC26XX_WEB_DEMO_ADC_DEMO
/*---------------------------------------------------------------------------*/
static void
res_get_handler_adc_dio23(void *request, void *response, uint8_t *buffer,
res_get_handler_adc_dio23(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_ADC_DIO23, request, response,
@ -136,7 +140,8 @@ RESOURCE(res_adc_dio23, "title=\"ADC DIO23\";rt=\"mV\"",
/*---------------------------------------------------------------------------*/
/* MPU resources and handler: Accelerometer and Gyro */
static void
res_get_handler_mpu_acc_x(void *request, void *response, uint8_t *buffer,
res_get_handler_mpu_acc_x(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_X, request, response,
@ -144,7 +149,8 @@ res_get_handler_mpu_acc_x(void *request, void *response, uint8_t *buffer,
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_mpu_acc_y(void *request, void *response, uint8_t *buffer,
res_get_handler_mpu_acc_y(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Y, request, response,
@ -152,7 +158,8 @@ res_get_handler_mpu_acc_y(void *request, void *response, uint8_t *buffer,
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_mpu_acc_z(void *request, void *response, uint8_t *buffer,
res_get_handler_mpu_acc_z(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Z, request, response,
@ -160,7 +167,8 @@ res_get_handler_mpu_acc_z(void *request, void *response, uint8_t *buffer,
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_mpu_gyro_x(void *request, void *response, uint8_t *buffer,
res_get_handler_mpu_gyro_x(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_X, request, response,
@ -168,7 +176,8 @@ res_get_handler_mpu_gyro_x(void *request, void *response, uint8_t *buffer,
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_mpu_gyro_y(void *request, void *response, uint8_t *buffer,
res_get_handler_mpu_gyro_y(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Y, request, response,
@ -176,7 +185,8 @@ res_get_handler_mpu_gyro_y(void *request, void *response, uint8_t *buffer,
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_mpu_gyro_z(void *request, void *response, uint8_t *buffer,
res_get_handler_mpu_gyro_z(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Z, request, response,
@ -199,7 +209,8 @@ RESOURCE(res_mpu_gyro_z, "title=\"Gyro Z\";rt=\"deg/sec\"",
/*---------------------------------------------------------------------------*/
/* TMP sensor resources and handlers: Object, Ambient */
static void
res_get_handler_obj_temp(void *request, void *response, uint8_t *buffer,
res_get_handler_obj_temp(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_TMP_OBJECT, request, response,
@ -207,7 +218,8 @@ res_get_handler_obj_temp(void *request, void *response, uint8_t *buffer,
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_amb_temp(void *request, void *response, uint8_t *buffer,
res_get_handler_amb_temp(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_TMP_AMBIENT, request, response,
@ -222,7 +234,8 @@ RESOURCE(res_tmp007_amb, "title=\"Temperature (Ambient)\";rt=\"C\"",
/*---------------------------------------------------------------------------*/
/* BMP sensor resources: Temperature, Pressure */
static void
res_get_handler_bmp_temp(void *request, void *response, uint8_t *buffer,
res_get_handler_bmp_temp(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BMP_TEMP, request, response,
@ -230,7 +243,8 @@ res_get_handler_bmp_temp(void *request, void *response, uint8_t *buffer,
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_bmp_press(void *request, void *response, uint8_t *buffer,
res_get_handler_bmp_press(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BMP_PRES, request, response,
@ -246,7 +260,8 @@ RESOURCE(res_bmp280_press,
/*---------------------------------------------------------------------------*/
/* HDC1000 sensor resources and handler: Temperature, Pressure */
static void
res_get_handler_hdc_temp(void *request, void *response, uint8_t *buffer,
res_get_handler_hdc_temp(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_HDC_TEMP, request, response,
@ -254,7 +269,8 @@ res_get_handler_hdc_temp(void *request, void *response, uint8_t *buffer,
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_hdc_humidity(void *request, void *response, uint8_t *buffer,
res_get_handler_hdc_humidity(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_HDC_HUMIDITY, request, response,
@ -269,7 +285,8 @@ RESOURCE(res_hdc1000_hum, "title=\"Humidity\";rt=\"%RH\"",
/*---------------------------------------------------------------------------*/
/* Illuminance resources and handler */
static void
res_get_handler_opt(void *request, void *response, uint8_t *buffer,
res_get_handler_opt(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_OPT_LIGHT, request, response,

View File

@ -42,20 +42,22 @@
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "dev/leds.h"
#include <string.h>
/*---------------------------------------------------------------------------*/
static void
res_post_handler_red(void *request, void *response, uint8_t *buffer,
res_post_handler_red(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
leds_toggle(LEDS_RED);
}
/*---------------------------------------------------------------------------*/
static void
res_post_handler_green(void *request, void *response, uint8_t *buffer,
res_post_handler_green(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
leds_toggle(LEDS_GREEN);
@ -81,14 +83,16 @@ RESOURCE(res_toggle_green,
#if BOARD_SMARTRF06EB
/*---------------------------------------------------------------------------*/
static void
res_post_handler_yellow(void *request, void *response, uint8_t *buffer,
res_post_handler_yellow(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
leds_toggle(LEDS_YELLOW);
}
/*---------------------------------------------------------------------------*/
static void
res_post_handler_orange(void *request, void *response, uint8_t *buffer,
res_post_handler_orange(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
leds_toggle(LEDS_ORANGE);

View File

@ -44,7 +44,7 @@
#if UIP_CONF_IPV6_RPL_LITE == 0
#include "rpl-private.h"
#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */
#include "rest-engine.h"
#include "coap-engine.h"
#include "coap.h"
#include "ti-lib.h"
@ -104,38 +104,38 @@ PROCESS(very_sleepy_demo_process, "CC13xx/CC26xx very sleepy process");
AUTOSTART_PROCESSES(&very_sleepy_demo_process);
/*---------------------------------------------------------------------------*/
static void
readings_get_handler(void *request, void *response, uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
readings_get_handler(coap_message_t *request, coap_message_t *response,
uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
int temp;
int voltage;
if(request != NULL) {
REST.get_header_accept(request, &accept);
coap_get_header_accept(request, &accept);
}
temp = batmon_sensor.value(BATMON_SENSOR_TYPE_TEMP);
voltage = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT);
if(accept == -1 || accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
if(accept == -1 || accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE,
"{\"temp\":{\"v\":%d,\"u\":\"C\"},"
"\"voltage\":{\"v\":%d,\"u\":\"mV\"}}",
temp, (voltage * 125) >> 5);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "Temp=%dC, Voltage=%dmV",
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "Temp=%dC, Voltage=%dmV",
temp, (voltage * 125) >> 5);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
REST.set_response_payload(response, not_supported_msg,
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, not_supported_msg,
strlen(not_supported_msg));
}
}
@ -144,39 +144,39 @@ RESOURCE(readings_resource, "title=\"Sensor Readings\";obs",
readings_get_handler, NULL, NULL, NULL);
/*---------------------------------------------------------------------------*/
static void
conf_get_handler(void *request, void *response, uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
conf_get_handler(coap_message_t *request, coap_message_t *response,
uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
if(request != NULL) {
REST.get_header_accept(request, &accept);
coap_get_header_accept(request, &accept);
}
if(accept == -1 || accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
if(accept == -1 || accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE,
"{\"config\":{\"mode\":%u,\"duration\":%lu,\"interval\":%lu}}",
config.mode, config.duration, config.interval);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE,
"Mode=%u, Duration=%lusecs, Interval=%lusecs",
config.mode, config.duration, config.interval);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
REST.set_response_payload(response, not_supported_msg,
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, not_supported_msg,
strlen(not_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
static void
conf_post_handler(void *request, void *response, uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
conf_post_handler(coap_message_t *request, coap_message_t *response,
uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const char *ptr = NULL;
char tmp_buf[16];
@ -186,7 +186,7 @@ conf_post_handler(void *request, void *response, uint8_t *buffer,
uint8_t post_status = POST_STATUS_NONE;
int rv;
rv = REST.get_post_variable(request, "mode", &ptr);
rv = coap_get_post_variable(request, "mode", &ptr);
if(rv && rv < 16) {
memset(tmp_buf, 0, sizeof(tmp_buf));
memcpy(tmp_buf, ptr, rv);
@ -203,7 +203,7 @@ conf_post_handler(void *request, void *response, uint8_t *buffer,
}
}
rv = REST.get_post_variable(request, "duration", &ptr);
rv = coap_get_post_variable(request, "duration", &ptr);
if(rv && rv < 16) {
memset(tmp_buf, 0, sizeof(tmp_buf));
memcpy(tmp_buf, ptr, rv);
@ -217,7 +217,7 @@ conf_post_handler(void *request, void *response, uint8_t *buffer,
}
}
rv = REST.get_post_variable(request, "interval", &ptr);
rv = coap_get_post_variable(request, "interval", &ptr);
if(rv && rv < 16) {
memset(tmp_buf, 0, sizeof(tmp_buf));
memcpy(tmp_buf, ptr, rv);
@ -232,13 +232,13 @@ conf_post_handler(void *request, void *response, uint8_t *buffer,
if((post_status & POST_STATUS_BAD) == POST_STATUS_BAD ||
post_status == POST_STATUS_NONE) {
REST.set_response_status(response, REST.status.BAD_REQUEST);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
coap_set_status_code(response, BAD_REQUEST_4_00);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE,
"mode=0|1&duration=[%u,%u]&interval=[%u,%u]",
NORMAL_OP_DURATION_MIN, NORMAL_OP_DURATION_MAX,
PERIODIC_INTERVAL_MIN, PERIODIC_INTERVAL_MAX);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
coap_set_payload(response, buffer, strlen((char *)buffer));
return;
}
@ -345,11 +345,11 @@ PROCESS_THREAD(very_sleepy_demo_process, ev, data)
event_new_config = process_alloc_event();
rest_init_engine();
coap_engine_init();
readings_resource.flags += IS_OBSERVABLE;
rest_activate_resource(&readings_resource, "sen/readings");
rest_activate_resource(&very_sleepy_conf, "very_sleepy_config");
coap_activate_resource(&readings_resource, "sen/readings");
coap_activate_resource(&very_sleepy_conf, "very_sleepy_config");
printf("Very Sleepy Demo Process\n");
@ -390,7 +390,7 @@ PROCESS_THREAD(very_sleepy_demo_process, ev, data)
* send notifications to observers as required.
*/
if(state == STATE_NOTIFY_OBSERVERS) {
REST.notify_subscribers(&readings_resource);
coap_notify_observers(&readings_resource);
state = STATE_NORMAL;
}

View File

@ -35,15 +35,15 @@
#include "net/ipv6/uip.h"
#include "net/ipv6/uip-ds6.h"
#include "tools/rpl-tools.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "sys/ctimer.h"
#include <stdio.h>
#include "dev/leds.h"
static void ct_callback(void *ptr);
static void put_post_led_toggle_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_toggle_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static char content[REST_MAX_CHUNK_SIZE];
static char content[COAP_MAX_CHUNK_SIZE];
static int content_len = 0;
static struct ctimer ct;
@ -77,7 +77,7 @@ RESOURCE(resource_led_toggle,
put_post_led_toggle_handler,
NULL);
static void
put_post_led_toggle_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
put_post_led_toggle_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
static int led_state = 0;
unsigned int accept = -1;
@ -110,10 +110,10 @@ put_post_led_toggle_handler(void *request, void *response, uint8_t *buffer, uint
break;
}
/* Return message */
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
/*---------------------------------------------------------------------------*/
@ -137,8 +137,8 @@ PROCESS_THREAD(start_app, ev, data)
rpl_tools_init(NULL);
} printf("Starting RPL node\n");
rest_init_engine();
rest_activate_resource(&resource_led_toggle, "Dongle/LED-toggle");
coap_engine_init();
coap_activate_resource(&resource_led_toggle, "Dongle/LED-toggle");
PROCESS_END();
}

View File

@ -36,7 +36,7 @@
#include "net/ipv6/uip.h"
#include "net/ipv6/uip-ds6.h"
#include "tools/rpl-tools.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "light-sensor.h"
#include "ht-sensor.h"
#include "dev/leds.h"
@ -46,19 +46,19 @@
#include <stdlib.h>
static void event_sensors_dr1175_handler(void);
static void get_sensors_dr1175_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_light_sensor_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_light_sensor_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_temperature_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_temperature_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_humidity_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_humidity_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_white_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_rgb_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_sensors_dr1175_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_light_sensor_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_light_sensor_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_temperature_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_temperature_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_humidity_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_humidity_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_white_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_rgb_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static char content[REST_MAX_CHUNK_SIZE];
static char content[COAP_MAX_CHUNK_SIZE];
static int content_len = 0;
#define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) { content_len += snprintf(content + content_len, sizeof(content) - content_len, __VA_ARGS__); } }
@ -90,26 +90,26 @@ EVENT_RESOURCE(resource_sensors_dr1175, /* name */
NULL, /* DELETE handler */
event_sensors_dr1175_handler); /* event handler */
static void
get_sensors_dr1175_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_sensors_dr1175_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.APPLICATION_JSON) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == APPLICATION_JSON) {
content_len = 0;
CONTENT_PRINTF("{\"DR1175\":[");
CONTENT_PRINTF("{\"Humidity\":\"%d\"},", ht_sensor.value(HT_SENSOR_HUM));
CONTENT_PRINTF("{\"Light\":\"%d\"},", light_sensor.value(0));
CONTENT_PRINTF("{\"Temp\":\"%d\"}", ht_sensor.value(HT_SENSOR_TEMP));
CONTENT_PRINTF("]}");
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, APPLICATION_JSON);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
static void
event_sensors_dr1175_handler()
{
/* Registered observers are notified and will trigger the GET handler to create the response. */
REST.notify_subscribers(&resource_sensors_dr1175);
coap_notify_observers(&resource_sensors_dr1175);
}
/*****************************************************/
/* Resource and handler to obtain light sensor value */
@ -121,15 +121,15 @@ RESOURCE(resource_light_sensor_value,
NULL,
NULL);
static void
get_light_sensor_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_light_sensor_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
content_len = 0;
CONTENT_PRINTF("%d", light_sensor.value(0));
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
/***************************************************/
@ -142,15 +142,15 @@ RESOURCE(resource_light_sensor_unit,
NULL,
NULL);
static void
get_light_sensor_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_light_sensor_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
content_len = 0;
CONTENT_PRINTF("Lux");
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
/***********************************************************/
@ -163,15 +163,15 @@ RESOURCE(resource_temperature_value,
NULL,
NULL);
static void
get_temperature_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_temperature_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
content_len = 0;
CONTENT_PRINTF("%d", ht_sensor.value(HT_SENSOR_TEMP));
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
/*********************************************************/
@ -184,15 +184,15 @@ RESOURCE(resource_temperature_unit,
NULL,
NULL);
static void
get_temperature_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_temperature_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
content_len = 0;
CONTENT_PRINTF("degrees C");
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
/********************************************************/
@ -205,15 +205,15 @@ RESOURCE(resource_humidity_value,
NULL,
NULL);
static void
get_humidity_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_humidity_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
content_len = 0;
CONTENT_PRINTF("%d", ht_sensor.value(HT_SENSOR_HUM));
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
/******************************************************/
@ -226,15 +226,15 @@ RESOURCE(resource_humidity_unit,
NULL,
NULL);
static void
get_humidity_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_humidity_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
content_len = 0;
CONTENT_PRINTF("relative %%");
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
/***************************************************/
@ -247,15 +247,15 @@ RESOURCE(resource_white_led,
put_post_white_led_handler,
NULL);
static void
put_post_white_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
put_post_white_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const uint8_t *request_content = NULL;
int level;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.get_request_payload(request, &request_content);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_get_payload(request, &request_content);
level = atoi((const char *)request_content);
CLIP(level, 255)
leds_set_level(level, LEDS_WHITE);
@ -271,7 +271,7 @@ RESOURCE(resource_rgb_led,
put_post_rgb_led_handler,
NULL);
static void
put_post_rgb_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
put_post_rgb_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const uint8_t *request_content = NULL;
char *pch;
@ -279,9 +279,9 @@ put_post_rgb_led_handler(void *request, void *response, uint8_t *buffer, uint16_
int index = 0;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.get_request_payload(request, &request_content);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_get_payload(request, &request_content);
pch = strtok((char *)request_content, " ");
while((pch != NULL) && (index != sizeof(RGB) / sizeof(int))) {
/* Convert token to int */
@ -306,13 +306,13 @@ RESOURCE(resource_led_d3_1174,
put_post_led_d3_1174_handler,
NULL);
static void
put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const uint8_t *request_content;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.get_request_payload(request, &request_content);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_get_payload(request, &request_content);
SET_LED(LEDS_GP0);
}
}
@ -326,13 +326,13 @@ RESOURCE(resource_led_d6_1174,
put_post_led_d6_1174_handler,
NULL);
static void
put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const uint8_t *request_content;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.get_request_payload(request, &request_content);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_get_payload(request, &request_content);
SET_LED(LEDS_GP1);
}
}
@ -357,18 +357,18 @@ PROCESS_THREAD(start_app, ev, data)
rpl_tools_init(NULL);
} printf("Starting RPL node\n");
rest_init_engine();
rest_activate_resource(&resource_light_sensor_value, "DR1175/LightSensor/Value");
rest_activate_resource(&resource_light_sensor_unit, "DR1175/LightSensor/Unit");
rest_activate_resource(&resource_temperature_unit, "DR1175/Temperature/Unit");
rest_activate_resource(&resource_temperature_value, "DR1175/Temperature/Value");
rest_activate_resource(&resource_humidity_unit, "DR1175/Humidity/Unit");
rest_activate_resource(&resource_humidity_value, "DR1175/Humidity/Value");
rest_activate_resource(&resource_white_led, "DR1175/WhiteLED");
rest_activate_resource(&resource_rgb_led, "DR1175/ColorLED/RGBValue");
rest_activate_resource(&resource_led_d3_1174, "DR1175/LED/D3On1174");
rest_activate_resource(&resource_led_d6_1174, "DR1175/LED/D6On1174");
rest_activate_resource(&resource_sensors_dr1175, "DR1175/AllSensors");
coap_engine_init();
coap_activate_resource(&resource_light_sensor_value, "DR1175/LightSensor/Value");
coap_activate_resource(&resource_light_sensor_unit, "DR1175/LightSensor/Unit");
coap_activate_resource(&resource_temperature_unit, "DR1175/Temperature/Unit");
coap_activate_resource(&resource_temperature_value, "DR1175/Temperature/Value");
coap_activate_resource(&resource_humidity_unit, "DR1175/Humidity/Unit");
coap_activate_resource(&resource_humidity_value, "DR1175/Humidity/Value");
coap_activate_resource(&resource_white_led, "DR1175/WhiteLED");
coap_activate_resource(&resource_rgb_led, "DR1175/ColorLED/RGBValue");
coap_activate_resource(&resource_led_d3_1174, "DR1175/LED/D3On1174");
coap_activate_resource(&resource_led_d6_1174, "DR1175/LED/D6On1174");
coap_activate_resource(&resource_sensors_dr1175, "DR1175/AllSensors");
/* Level of LEDS=0, so no light after start-up */
leds_on(LEDS_WHITE | LEDS_RED | LEDS_GREEN | LEDS_BLUE);

View File

@ -35,30 +35,30 @@
#include "net/ipv6/uip.h"
#include "net/ipv6/uip-ds6.h"
#include "tools/rpl-tools.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "dev/leds.h"
#include "button-sensor.h"
#include "pot-sensor.h"
#include <stdio.h>
#include <stdlib.h>
static char content[REST_MAX_CHUNK_SIZE];
static char content[COAP_MAX_CHUNK_SIZE];
static int content_len = 0;
static void event_sensors_dr1199_handler();
static void get_sensors_dr1199_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_switch_sw1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_switch_sw2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_switch_sw3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_switch_sw4_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_switch_dio8_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_pot_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_d1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_d2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_d3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_all_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_sensors_dr1199_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_switch_sw1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_switch_sw2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_switch_sw3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_switch_sw4_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_switch_dio8_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_pot_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_d1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_d2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_d3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_led_all_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
#define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) { content_len += snprintf(content + content_len, sizeof(content) - content_len, __VA_ARGS__); } }
@ -93,25 +93,25 @@ EVENT_RESOURCE(resource_sensors_dr1199, /* name */
NULL, /* DELETE handler */
event_sensors_dr1199_handler); /* event handler */
static void
get_sensors_dr1199_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_sensors_dr1199_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.APPLICATION_JSON) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == APPLICATION_JSON) {
content_len = 0;
CONTENT_PRINTF("{\"DR1199\":[");
CONTENT_PRINTF("{\"Switch\":\"0x%X\"},", button_sensor.value(0));
CONTENT_PRINTF("{\"Pot\":\"%d\"}", pot_sensor.value(0));
CONTENT_PRINTF("]}");
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, APPLICATION_JSON);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
static void
event_sensors_dr1199_handler()
{
/* Registered observers are notified and will trigger the GET handler to create the response. */
REST.notify_subscribers(&resource_sensors_dr1199);
coap_notify_observers(&resource_sensors_dr1199);
}
/***********************************************/
/* Resource and handler to obtain switch value */
@ -123,15 +123,15 @@ RESOURCE(resource_switch_sw1,
NULL,
NULL);
static void
get_switch_sw1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_switch_sw1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
content_len = 0;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
PARSE_SWITCH(1)
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
RESOURCE(resource_switch_sw2,
@ -141,15 +141,15 @@ RESOURCE(resource_switch_sw2,
NULL,
NULL);
static void
get_switch_sw2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_switch_sw2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
content_len = 0;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
PARSE_SWITCH(2)
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
RESOURCE(resource_switch_sw3,
@ -159,15 +159,15 @@ RESOURCE(resource_switch_sw3,
NULL,
NULL);
static void
get_switch_sw3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_switch_sw3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
content_len = 0;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
PARSE_SWITCH(3)
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
RESOURCE(resource_switch_sw4,
@ -177,15 +177,15 @@ RESOURCE(resource_switch_sw4,
NULL,
NULL);
static void
get_switch_sw4_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_switch_sw4_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
content_len = 0;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
PARSE_SWITCH(4)
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
RESOURCE(resource_switch_dio8,
@ -195,15 +195,15 @@ RESOURCE(resource_switch_dio8,
NULL,
NULL);
static void
get_switch_dio8_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_switch_dio8_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
content_len = 0;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
PARSE_SWITCH(0)
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
/*******************************************************/
@ -216,15 +216,15 @@ RESOURCE(resource_pot,
NULL,
NULL);
static void
get_pot_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_pot_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
content_len = 0;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
CONTENT_PRINTF("%d", pot_sensor.value(0));
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
/************************************/
@ -237,13 +237,13 @@ RESOURCE(resource_led_d1,
put_post_led_d1_handler,
NULL);
static void
put_post_led_d1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
put_post_led_d1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const uint8_t *request_content;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.get_request_payload(request, &request_content);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_get_payload(request, &request_content);
SET_LED(LEDS_GREEN)
}
}
@ -254,13 +254,13 @@ RESOURCE(resource_led_d2,
put_post_led_d2_handler,
NULL);
static void
put_post_led_d2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
put_post_led_d2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const uint8_t *request_content;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.get_request_payload(request, &request_content);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_get_payload(request, &request_content);
SET_LED(LEDS_BLUE)
}
}
@ -271,13 +271,13 @@ RESOURCE(resource_led_d3,
put_post_led_d3_handler,
NULL);
static void
put_post_led_d3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
put_post_led_d3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const uint8_t *request_content;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.get_request_payload(request, &request_content);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_get_payload(request, &request_content);
SET_LED(LEDS_RED)
}
}
@ -288,13 +288,13 @@ RESOURCE(resource_led_d3_1174,
put_post_led_d3_1174_handler,
NULL);
static void
put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const uint8_t *request_content;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.get_request_payload(request, &request_content);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_get_payload(request, &request_content);
SET_LED(LEDS_GP0);
}
}
@ -305,13 +305,13 @@ RESOURCE(resource_led_d6_1174,
put_post_led_d6_1174_handler,
NULL);
static void
put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const uint8_t *request_content;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.get_request_payload(request, &request_content);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_get_payload(request, &request_content);
SET_LED(LEDS_GP1);
}
}
@ -322,13 +322,13 @@ RESOURCE(resource_led_all,
put_post_led_all_handler,
NULL);
static void
put_post_led_all_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
put_post_led_all_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const uint8_t *request_content;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.get_request_payload(request, &request_content);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_get_payload(request, &request_content);
if(atoi((const char *)request_content) != 0) {
leds_on(LEDS_ALL);
} else {
@ -358,20 +358,20 @@ PROCESS_THREAD(start_app, ev, data)
rpl_tools_init(NULL);
} printf("Starting RPL node\n");
rest_init_engine();
rest_activate_resource(&resource_switch_sw1, "DR1199/Switch/SW1");
rest_activate_resource(&resource_switch_sw2, "DR1199/Switch/SW2");
rest_activate_resource(&resource_switch_sw3, "DR1199/Switch/SW3");
rest_activate_resource(&resource_switch_sw4, "DR1199/Switch/SW4");
rest_activate_resource(&resource_switch_dio8, "DR1199/Switch/DIO8");
rest_activate_resource(&resource_pot, "DR1199/Potentiometer");
rest_activate_resource(&resource_led_d1, "DR1199/LED/D1");
rest_activate_resource(&resource_led_d2, "DR1199/LED/D2");
rest_activate_resource(&resource_led_d3, "DR1199/LED/D3");
rest_activate_resource(&resource_led_d3_1174, "DR1199/LED/D3On1174");
rest_activate_resource(&resource_led_d6_1174, "DR1199/LED/D6On1174");
rest_activate_resource(&resource_led_all, "DR1199/LED/All");
rest_activate_resource(&resource_sensors_dr1199, "DR1199/AllSensors");
coap_engine_init();
coap_activate_resource(&resource_switch_sw1, "DR1199/Switch/SW1");
coap_activate_resource(&resource_switch_sw2, "DR1199/Switch/SW2");
coap_activate_resource(&resource_switch_sw3, "DR1199/Switch/SW3");
coap_activate_resource(&resource_switch_sw4, "DR1199/Switch/SW4");
coap_activate_resource(&resource_switch_dio8, "DR1199/Switch/DIO8");
coap_activate_resource(&resource_pot, "DR1199/Potentiometer");
coap_activate_resource(&resource_led_d1, "DR1199/LED/D1");
coap_activate_resource(&resource_led_d2, "DR1199/LED/D2");
coap_activate_resource(&resource_led_d3, "DR1199/LED/D3");
coap_activate_resource(&resource_led_d3_1174, "DR1199/LED/D3On1174");
coap_activate_resource(&resource_led_d6_1174, "DR1199/LED/D6On1174");
coap_activate_resource(&resource_led_all, "DR1199/LED/All");
coap_activate_resource(&resource_sensors_dr1199, "DR1199/AllSensors");
/* If sensor process generates an event, call event_handler of resource.
This will make this resource observable by the client */
while(1) {
@ -382,4 +382,3 @@ PROCESS_THREAD(start_app, ev, data)
PROCESS_END();
}

View File

@ -37,15 +37,15 @@
#include "net/ipv6/uip.h"
#include "net/linkaddr.h"
#include "rpl-tools.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include <stdio.h>
#include <stdlib.h>
#include <AppHardwareApi.h>
static void set_tx_power_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_tx_power_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void set_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static char content[REST_MAX_CHUNK_SIZE];
static char content[COAP_MAX_CHUNK_SIZE];
static int content_len = 0;
#define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) content_len += snprintf(content+content_len, sizeof(content)-content_len, __VA_ARGS__); }
@ -63,15 +63,15 @@ RESOURCE(resource_set_tx_power,
set_tx_power_handler,
NULL);
static void
set_tx_power_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
set_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const uint8_t *request_content = NULL;
int tx_level;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.get_request_payload(request, &request_content);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_get_payload(request, &request_content);
tx_level = atoi((const char *)request_content);
NETSTACK_RADIO.set_value(RADIO_PARAM_TXPOWER, tx_level);
}
@ -84,17 +84,17 @@ RESOURCE(resource_get_tx_power,
NULL,
NULL);
static void
get_tx_power_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
int tx_level;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
content_len = 0;
NETSTACK_RADIO.get_value(RADIO_PARAM_TXPOWER, &tx_level);
CONTENT_PRINTF("%d", tx_level);
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
/*---------------------------------------------------------------------------*/
@ -113,9 +113,9 @@ PROCESS_THREAD(start_app, ev, data)
}
printf("Starting RPL node\n");
rest_init_engine();
rest_activate_resource(&resource_set_tx_power, "Set-TX-Power");
rest_activate_resource(&resource_get_tx_power, "Get-TX-Power");
coap_engine_init();
coap_activate_resource(&resource_set_tx_power, "Set-TX-Power");
coap_activate_resource(&resource_get_tx_power, "Get-TX-Power");
PROCESS_END();
}

View File

@ -42,7 +42,7 @@
#include "net/mac/tsch/tsch-schedule.h"
#include "net/netstack.h"
#include "dev/slip.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "rpl-tools.h"
#include <stdio.h>
@ -56,10 +56,10 @@
static uip_ipaddr_t prefix;
static uint8_t prefix_set;
static void get_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_last_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_rssi_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_last_rssi_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static char content[REST_MAX_CHUNK_SIZE];
static char content[COAP_MAX_CHUNK_SIZE];
static int content_len = 0;
#define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) content_len += snprintf(content+content_len, sizeof(content)-content_len, __VA_ARGS__); }
@ -74,17 +74,17 @@ RESOURCE(resource_get_rssi,
NULL,
NULL);
static void
get_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_rssi_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
int rssi_level;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
content_len = 0;
NETSTACK_RADIO.get_value(RADIO_PARAM_RSSI, &rssi_level);
CONTENT_PRINTF("%d", rssi_level);
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
@ -95,17 +95,17 @@ RESOURCE(resource_get_last_rssi,
NULL,
NULL);
static void
get_last_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_last_rssi_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
int last_rssi_level;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
content_len = 0;
NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_RSSI, &last_rssi_level);
CONTENT_PRINTF("%d", last_rssi_level);
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
@ -159,9 +159,9 @@ PROCESS_THREAD(border_router_process, ev, data)
rpl_tools_init(&prefix);
rest_init_engine();
rest_activate_resource(&resource_get_rssi, "Get-RSSI");
rest_activate_resource(&resource_get_last_rssi, "Get-Last-RSSI");
coap_engine_init();
coap_activate_resource(&resource_get_rssi, "Get-RSSI");
coap_activate_resource(&resource_get_last_rssi, "Get-Last-RSSI");
PROCESS_END();

View File

@ -36,22 +36,22 @@
#include "net/ipv6/uip.h"
#include "net/linkaddr.h"
#include "rpl-tools.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "sys/ctimer.h"
#include "dev/uart-driver.h"
#include "uart1.h"
#include <AppHardwareApi.h>
static void get_coap_rx_uart1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void get_coap_rx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void event_coap_rx_uart1_handler(void);
static void put_post_tx_uart1_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void put_post_tx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
static void string2uart1(uint8_t *c);
static int handleRxChar(uint8_t c);
static int get_ringbuf(uint8_t *c);
static int put_ringbuf(uint8_t c);
/* COAP helpers */
static char content[REST_MAX_CHUNK_SIZE];
static char content[COAP_MAX_CHUNK_SIZE];
static int content_len = 0;
#define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) content_len += snprintf(content+content_len, sizeof(content)-content_len, __VA_ARGS__); }
@ -85,15 +85,15 @@ EVENT_RESOURCE(resource_coap_rx_uart1, /* name */
NULL, /* DELETE handler */
event_coap_rx_uart1_handler); /* event handler */
static void
get_coap_rx_uart1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
get_coap_rx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
content_len = 0;
CONTENT_PRINTF("%s", rx_buf);
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, (uint8_t *)content, content_len);
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, (uint8_t *)content, content_len);
}
}
@ -101,7 +101,7 @@ static void
event_coap_rx_uart1_handler(void)
{
/* Registered observers are notified and will trigger the GET handler to create the response. */
REST.notify_subscribers(&resource_coap_rx_uart1);
coap_notify_observers(&resource_coap_rx_uart1);
}
/*****************************************************************************/
@ -115,14 +115,14 @@ RESOURCE(resource_coap_tx_uart1, /* name */
NULL); /* DELETE handler */
static void
put_post_tx_uart1_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
put_post_tx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const uint8_t *request_content = NULL;
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.get_request_payload(request, &request_content);
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_get_payload(request, &request_content);
string2uart1((uint8_t *)request_content);
}
}
@ -154,9 +154,9 @@ PROCESS_THREAD(start_app, ev, data)
}
printf("Starting RPL node\n");
rest_init_engine();
rest_activate_resource(&resource_coap_rx_uart1, "UART1-RX");
rest_activate_resource(&resource_coap_tx_uart1, "UART1-TX");
coap_engine_init();
coap_activate_resource(&resource_coap_rx_uart1, "UART1-RX");
coap_activate_resource(&resource_coap_tx_uart1, "UART1-TX");
PROCESS_END();
}
@ -256,4 +256,3 @@ put_ringbuf(uint8_t c)
uart1_enable_interrupts();
return return_val;
}

View File

@ -5,10 +5,10 @@ $(error Please specify whether coap-client or coap-server should be built)
endif
ifneq ($(filter coap-client coap-client.flash, $(MAKECMDGOALS)),)
ifeq ($(SERVER_IPV6_ADDR),)
$(error Please define SERVER_IPV6_ADDR=<full ipv6 addr>)
ifeq ($(SERVER_IPV6_EP),)
$(error Please define SERVER_IPV6_EP=<full-coap-IPv6-URI>)
else
CFLAGS += -DSERVER_IPV6_ADDR=\"$(SERVER_IPV6_ADDR)\"
CFLAGS += -DSERVER_IPV6_EP=\"$(SERVER_IPV6_EP)\"
CFLAGS += -DDEVICE_NAME=\"nRF52_DK_CoAP_Client\"
endif
else

View File

@ -51,6 +51,7 @@
#include "contiki.h"
#include "contiki-net.h"
#include "coap-engine.h"
#include "coap-endpoint.h"
#include "dev/button-sensor.h"
#include "dev/leds.h"
@ -63,13 +64,11 @@
#endif
/*----------------------------------------------------------------------------*/
#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT)
#define OBS_RESOURCE_URI "lights/led3"
#define SUBS_LED LEDS_4
#define OBS_LED LEDS_3
/*----------------------------------------------------------------------------*/
static uip_ipaddr_t server_ipaddr[1]; /* holds the server ip address */
static coap_observee_t *obs;
static struct ctimer ct;
/*----------------------------------------------------------------------------*/
@ -146,11 +145,11 @@ notification_callback(coap_observee_t *obs, void *notification,
PROCESS_THREAD(er_example_observe_client, ev, data)
{
PROCESS_BEGIN();
uiplib_ipaddrconv(SERVER_IPV6_ADDR, server_ipaddr);
static coap_endpoint_t server_endpoint;
coap_endpoint_parse(SERVER_IPV6_EP, strlen(SERVER_IPV6_EP), &server_endpoint);
/* receives all CoAP messages */
coap_init_engine();
coap_engine_init();
#if PLATFORM_HAS_BUTTON
SENSORS_ACTIVATE(button_1);
@ -164,7 +163,7 @@ PROCESS_THREAD(er_example_observe_client, ev, data)
if (ev == sensors_event) {
if (data == &button_1 && button_1.value(BUTTON_SENSOR_VALUE_STATE) == 0) {
PRINTF("Starting observation\n");
obs = coap_obs_request_registration(server_ipaddr, REMOTE_PORT,
obs = coap_obs_request_registration(&server_endpoint,
OBS_RESOURCE_URI, notification_callback,
NULL);
}

View File

@ -51,7 +51,7 @@
#include <string.h>
#include "contiki.h"
#include "contiki-net.h"
#include "rest-engine.h"
#include "coap-engine.h"
#include "uip.h"
#include "dev/button-sensor.h"
#include "dev/leds.h"
@ -63,7 +63,7 @@
* Resources to be activated need to be imported through the extern keyword.
* The build system automatically compiles the resources in the corresponding sub-directory.
*/
extern resource_t res_led3;
extern coap_resource_t res_led3;
static void
print_local_addresses(void)
@ -99,13 +99,13 @@ PROCESS_THREAD(er_example_server, ev, data)
PRINTF("uIP buffer: %u\n", UIP_BUFSIZE);
PRINTF("LL header: %u\n", UIP_LLH_LEN);
PRINTF("IP+UDP header: %u\n", UIP_IPUDPH_LEN);
PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE);
PRINTF("REST max chunk: %u\n", COAP_MAX_CHUNK_SIZE);
print_local_addresses();
/* Initialize the REST engine. */
rest_init_engine();
rest_activate_resource(&res_led3, "lights/led3");
coap_engine_init();
coap_activate_resource(&res_led3, "lights/led3");
SENSORS_ACTIVATE(button_1);

View File

@ -40,22 +40,25 @@
#include <string.h>
#include "contiki.h"
#include "rest-engine.h"
#include "coap.h"
#include "coap-engine.h"
#include "dev/leds.h"
#define DEBUG DEBUG_NONE
#include "net/ipv6/uip-debug.h"
static void
res_post_put_handler(void *request, void *response, uint8_t *buffer,
res_post_put_handler(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset);
static void
res_get_handler(void *request, void *response, uint8_t *buffer,
res_get_handler(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset);
static void
res_event_handler();
res_event_handler(void);
/*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/
EVENT_RESOURCE(res_led3,
@ -68,30 +71,30 @@ EVENT_RESOURCE(res_led3,
);
static void
res_post_put_handler(void *request, void *response, uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
res_post_put_handler(coap_message_t *request, coap_message_t *response,
uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const uint8_t *payload;
REST.get_request_payload(request, &payload);
coap_get_payload(request, &payload);
if (*payload == '0' || *payload == '1') {
if (*payload == '1') {
if(*payload == '0' || *payload == '1') {
if(*payload == '1') {
leds_on(LEDS_3);
} else {
leds_off(LEDS_3);
}
REST.notify_subscribers(&res_led3);
REST.set_response_status(response, REST.status.CHANGED);
coap_notify_observers(&res_led3);
coap_set_status_code(response, CHANGED_2_04);
} else {
REST.set_response_status(response, REST.status.BAD_REQUEST);
coap_set_status_code(response, BAD_REQUEST_4_00);
}
}
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "%d", (leds_get() & LEDS_3) ? 1 : 0));
coap_set_header_content_format(response, TEXT_PLAIN);
coap_set_payload(response, buffer, snprintf((char *)buffer, preferred_size, "%d", (leds_get() & LEDS_3) ? 1 : 0));
}
/*
@ -102,5 +105,5 @@ static void
res_event_handler()
{
/* Notify the registered observers which will trigger the res_get_handler to create the response. */
REST.notify_subscribers(&res_led3);
coap_notify_observers(&res_led3);
}

View File

@ -0,0 +1,31 @@
MAKE_WITH_DTLS ?= 0
ifeq ($(MAKE_WITH_DTLS),1)
TINYDTLS_PATH := os/net/security/tinydtls
ifeq (${wildcard $(CONTIKI)/$(TINYDTLS_PATH)/Makefile},)
${error Could not find the tinyDTLS submodule. Please run "git submodule update --init" and try again}
endif
CFLAGS += -DWITH_DTLS=1
MODULES += os/net/app-layer/coap/tinydtls-support
MODULES += $(TINYDTLS_PATH) ${addprefix $(TINYDTLS_PATH)/,aes sha2 ecc}
MAKE_COAP_DTLS_KEYSTORE_NONE := 0
MAKE_COAP_DTLS_KEYSTORE_SIMPLE := 1
MAKE_COAP_DTLS_KEYSTORE_LWM2M := 2
MAKE_COAP_DTLS_KEYSTORE ?= MAKE_COAP_DTLS_KEYSTORE_LWM2M
ifeq ($(MAKE_COAP_DTLS_KEYSTORE),MAKE_COAP_DTLS_KEYSTORE_SIMPLE)
CFLAGS += -DCOAP_DTLS_KEYSTORE_CONF_WITH_SIMPLE=1
else ifeq ($(MAKE_COAP_DTLS_KEYSTORE),MAKE_COAP_DTLS_KEYSTORE_LWM2M)
CFLAGS += -DCOAP_DTLS_KEYSTORE_CONF_WITH_LWM2M=1
else ifeq ($(MAKE_COAP_DTLS_KEYSTORE),MAKE_COAP_DTLS_KEYSTORE_NONE)
# No C flag needed for no keystore
else
${error Unsupported CoAP DTLS keystore: $(MAKE_COAP_DTLS_KEYSTORE)}
endif
endif

View File

@ -36,24 +36,23 @@
* Lars Schmertmann <SmallLars@t-online.de>
*/
#include <stdio.h>
/**
* \addtogroup coap
* @{
*/
#include <string.h>
#include <inttypes.h>
#include "coap.h"
#include "coap-block1.h"
#define DEBUG 0
#if DEBUG
#define PRINTF(...) printf(__VA_ARGS__)
#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#define PRINTLLADDR(addr)
#endif
/* Log configuration */
#include "coap-log.h"
#define LOG_MODULE "coap-block1"
#define LOG_LEVEL LOG_LEVEL_COAP
/*----------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/**
* \brief Block 1 support within a coap-ressource
@ -77,39 +76,39 @@
* -1 if initialisation failed
*/
int
coap_block1_handler(void *request, void *response, uint8_t *target, size_t *len, size_t max_len)
coap_block1_handler(coap_message_t *request, coap_message_t *response,
uint8_t *target, size_t *len, size_t max_len)
{
const uint8_t *payload = 0;
int pay_len = REST.get_request_payload(request, &payload);
int pay_len = coap_get_payload(request, &payload);
if(!pay_len || !payload) {
erbium_status_code = REST.status.BAD_REQUEST;
coap_status_code = BAD_REQUEST_4_00;
coap_error_message = "NoPayload";
return -1;
}
coap_packet_t *packet = (coap_packet_t *)request;
if(packet->block1_offset + pay_len > max_len) {
erbium_status_code = REST.status.REQUEST_ENTITY_TOO_LARGE;
if(request->block1_offset + pay_len > max_len) {
coap_status_code = REQUEST_ENTITY_TOO_LARGE_4_13;
coap_error_message = "Message to big";
return -1;
}
if(target && len) {
memcpy(target + packet->block1_offset, payload, pay_len);
*len = packet->block1_offset + pay_len;
memcpy(target + request->block1_offset, payload, pay_len);
*len = request->block1_offset + pay_len;
}
if(IS_OPTION(packet, COAP_OPTION_BLOCK1)) {
PRINTF("Blockwise: block 1 request: Num: %u, More: %u, Size: %u, Offset: %u\n",
packet->block1_num,
packet->block1_more,
packet->block1_size,
packet->block1_offset);
if(coap_is_option(request, COAP_OPTION_BLOCK1)) {
LOG_DBG("Blockwise: block 1 request: Num: %"PRIu32
", More: %u, Size: %u, Offset: %"PRIu32"\n",
request->block1_num,
request->block1_more,
request->block1_size,
request->block1_offset);
coap_set_header_block1(response, packet->block1_num, packet->block1_more, packet->block1_size);
if(packet->block1_more) {
coap_set_header_block1(response, request->block1_num, request->block1_more, request->block1_size);
if(request->block1_more) {
coap_set_status_code(response, CONTINUE_2_31);
return 1;
}
@ -117,3 +116,5 @@ coap_block1_handler(void *request, void *response, uint8_t *target, size_t *len,
return 0;
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -36,12 +36,20 @@
* Lars Schmertmann <SmallLars@t-online.de>
*/
/**
* \addtogroup coap
* @{
*/
#ifndef COAP_BLOCK1_H_
#define COAP_BLOCK1_H_
#include "coap.h"
#include <stddef.h>
#include <stdint.h>
int coap_block1_handler(void *request, void *response, uint8_t *target, size_t *len, size_t max_len);
int coap_block1_handler(coap_message_t *request, coap_message_t *response,
uint8_t *target, size_t *len, size_t max_len);
#endif /* COAP_BLOCK1_H_ */
/** @} */

View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* CoAP implementation for the REST Engine.
* \author
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
/**
* \addtogroup coap
* @{
*/
#include "coap-engine.h"
#include "coap-blocking-api.h"
#include "sys/cc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
/* Log configuration */
#include "coap-log.h"
#define LOG_MODULE "coap-blocking-api"
#define LOG_LEVEL LOG_LEVEL_COAP
/*---------------------------------------------------------------------------*/
/*- Client Part -------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void
coap_blocking_request_callback(void *callback_data, coap_message_t *response)
{
coap_request_state_t *state = (coap_request_state_t *)callback_data;
state->response = response;
process_poll(state->process);
}
/*---------------------------------------------------------------------------*/
PT_THREAD(coap_blocking_request
(coap_request_state_t *state, process_event_t ev,
coap_endpoint_t *remote_ep,
coap_message_t *request,
coap_blocking_response_handler_t request_callback))
{
PT_BEGIN(&state->pt);
static uint32_t res_block;
static uint8_t more;
static uint8_t block_error;
state->block_num = 0;
state->response = NULL;
state->process = PROCESS_CURRENT();
more = 0;
res_block = 0;
block_error = 0;
do {
request->mid = coap_get_mid();
if((state->transaction = coap_new_transaction(request->mid, remote_ep))) {
state->transaction->callback = coap_blocking_request_callback;
state->transaction->callback_data = state;
if(state->block_num > 0) {
coap_set_header_block2(request, state->block_num, 0,
COAP_MAX_CHUNK_SIZE);
}
state->transaction->message_len = coap_serialize_message(request,
state->
transaction->
message);
coap_send_transaction(state->transaction);
LOG_DBG("Requested #%"PRIu32" (MID %u)\n", state->block_num, request->mid);
PT_YIELD_UNTIL(&state->pt, ev == PROCESS_EVENT_POLL);
if(!state->response) {
LOG_WARN("Server not responding\n");
PT_EXIT(&state->pt);
}
coap_get_header_block2(state->response, &res_block, &more, NULL, NULL);
LOG_DBG("Received #%"PRIu32"%s (%u bytes)\n", res_block, more ? "+" : "",
state->response->payload_len);
if(res_block == state->block_num) {
request_callback(state->response);
++(state->block_num);
} else {
LOG_WARN("WRONG BLOCK %"PRIu32"/%"PRIu32"\n",
res_block, state->block_num);
++block_error;
}
} else {
LOG_WARN("Could not allocate transaction buffer");
PT_EXIT(&state->pt);
}
} while(more && block_error < COAP_MAX_ATTEMPTS);
PT_END(&state->pt);
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \addtogroup coap
* @{
*/
#ifndef COAP_BLOCKING_API_H_
#define COAP_BLOCKING_API_H_
#include "sys/pt.h"
#include "coap-transactions.h"
/*---------------------------------------------------------------------------*/
/*- Client Part -------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
typedef struct coap_request_state {
struct pt pt;
struct process *process;
coap_transaction_t *transaction;
coap_message_t *response;
uint32_t block_num;
} coap_request_state_t;
typedef void (* coap_blocking_response_handler_t)(coap_message_t *response);
PT_THREAD(coap_blocking_request
(coap_request_state_t *state, process_event_t ev,
coap_endpoint_t *remote,
coap_message_t *request,
coap_blocking_response_handler_t request_callback));
#define COAP_BLOCKING_REQUEST(server_endpoint, request, chunk_handler) \
{ \
static coap_request_state_t request_state; \
PT_SPAWN(process_pt, &request_state.pt, \
coap_blocking_request(&request_state, ev, \
server_endpoint, \
request, chunk_handler) \
); \
}
#endif /* COAP_BLOCKING_API_H_ */
/** @} */

View File

@ -0,0 +1,159 @@
/*
* Copyright (c) 2016, SICS Swedish ICT
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
/**
* \file
* Callback API for doing CoAP requests
* Adapted from the blocking API
* \author
* Joakim Eriksson, joakime@sics.se
*/
/**
* \addtogroup coap
* @{
*/
#include "coap-engine.h"
#include "coap-callback-api.h"
#include "coap-transactions.h"
#include "sys/cc.h"
#include <stdlib.h>
#include <string.h>
/* Log configuration */
#include "coap-log.h"
#define LOG_MODULE "coap-callback-api"
#define LOG_LEVEL LOG_LEVEL_COAP
/* These should go into the state struct so that we can have multiple
requests */
static uint32_t res_block;
static uint8_t more;
static uint8_t block_error;
static void coap_request_callback(void *callback_data, coap_message_t *response);
/*---------------------------------------------------------------------------*/
static void
progress_request(coap_request_state_t *state) {
coap_message_t *request = state->request;
request->mid = coap_get_mid();
if((state->transaction =
coap_new_transaction(request->mid, state->remote_endpoint))) {
state->transaction->callback = coap_request_callback;
state->transaction->callback_data = state;
if(state->block_num > 0) {
coap_set_header_block2(request, state->block_num, 0,
COAP_MAX_CHUNK_SIZE);
}
state->transaction->message_len =
coap_serialize_message(request, state->transaction->message);
coap_send_transaction(state->transaction);
LOG_DBG("Requested #%lu (MID %u)\n", (unsigned long)state->block_num,
request->mid);
}
}
/*---------------------------------------------------------------------------*/
static void
coap_request_callback(void *callback_data, coap_message_t *response)
{
coap_request_state_t *state = (coap_request_state_t *)callback_data;
uint32_t res_block1;
state->response = response;
LOG_DBG("request callback\n");
if(!state->response) {
LOG_WARN("Server not responding giving up...\n");
state->callback(state);
return;
}
/* Got a response */
coap_get_header_block2(state->response, &res_block, &more, NULL, NULL);
coap_get_header_block1(state->response, &res_block1, NULL, NULL, NULL);
LOG_DBG("Received #%lu%s B1:%lu (%u bytes)\n",
(unsigned long)res_block, (unsigned)more ? "+" : "",
(unsigned long)res_block1,
state->response->payload_len);
if(res_block == state->block_num) {
/* Call the callback function as we have more data */
state->callback(state);
/* this is only for counting BLOCK2 blocks.*/
++(state->block_num);
} else {
LOG_WARN("WRONG BLOCK %lu/%lu\n", (unsigned long)res_block,
(unsigned long)state->block_num);
++block_error;
}
if(more && block_error < COAP_MAX_ATTEMPTS) {
progress_request(state);
} else {
/* failure - now we give up and notify the callback */
state->response = NULL;
state->callback(state);
}
}
/*---------------------------------------------------------------------------*/
void
coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint,
coap_message_t *request,
void (*callback)(coap_request_state_t *state))
{
/* can we have these variables shared between multiple requests? */
/* ripped from blocking request */
more = 0;
res_block = 0;
block_error = 0;
state->block_num = 0;
state->response = NULL;
state->request = request;
state->remote_endpoint = endpoint;
state->callback = callback;
progress_request(state);
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, Swedish Institute of Computer Science.
* Copyright (c) 2016, SICS Swedish ICT
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,65 +26,48 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
/**
* \file
* A set of debugging tools for the IP stack
* Callback API for doing CoAP requests
* Adapted from the blocking API
* \author
* Nicolas Tsiftes <nvt@sics.se>
* Niclas Finne <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
* Joakim Eriksson, joakime@sics.se
*/
#include "net/ipv6/uip-debug.h"
#include "net/ipv6/ip64-addr.h"
/**
* \addtogroup coap
* @{
*/
#ifndef COAP_CALLBACK_API_H_
#define COAP_CALLBACK_API_H_
#include "coap-engine.h"
#include "coap-transactions.h"
#include "sys/cc.h"
/*---------------------------------------------------------------------------*/
void
uip_debug_ipaddr_print(const uip_ipaddr_t *addr)
{
uint16_t a;
unsigned int i;
int f;
if(addr == NULL) {
PRINTA("(NULL IP addr)");
return;
}
if(ip64_addr_is_ipv4_mapped_addr(addr)) {
/*
* Printing IPv4-mapped addresses is done according to RFC 4291 [1]
*
* "An alternative form that is sometimes more
* convenient when dealing with a mixed environment
* of IPv4 and IPv6 nodes is x:x:x:x:x:x:d.d.d.d,
* where the 'x's are the hexadecimal values of the
* six high-order 16-bit pieces of the address, and
* the 'd's are the decimal values of the four
* low-order 8-bit pieces of the address (standard
* IPv4 representation)."
*
* [1] https://tools.ietf.org/html/rfc4291#page-4
*/
PRINTA("::FFFF:%u.%u.%u.%u", addr->u8[12], addr->u8[13], addr->u8[14], addr->u8[15]);
} else {
for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) {
a = (addr->u8[i] << 8) + addr->u8[i + 1];
if(a == 0 && f >= 0) {
if(f++ == 0) {
PRINTA("::");
}
} else {
if(f > 0) {
f = -1;
} else if(i > 0) {
PRINTA(":");
}
PRINTA("%x", a);
}
}
}
}
/*- Client Part -------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
typedef struct coap_request_state coap_request_state_t;
struct coap_request_state {
coap_transaction_t *transaction;
coap_message_t *response;
coap_message_t *request;
coap_endpoint_t *remote_endpoint;
uint32_t block_num;
void *user_data;
coap_timer_t coap_timer;
void (*callback)(coap_request_state_t *state);
};
void coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint,
coap_message_t *request,
void (*callback)(coap_request_state_t *state));
#endif /* COAP_CALLBACK_API_H_ */
/** @} */

View File

@ -36,8 +36,33 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#ifndef ER_COAP_CONF_H_
#define ER_COAP_CONF_H_
/**
* \addtogroup coap
* @{
*/
#ifndef COAP_CONF_H_
#define COAP_CONF_H_
#include "contiki.h"
/*
* The maximum buffer size that is provided for resource responses and must be
* respected due to the limited IP buffer. Larger data must be handled by the
* resource and will be sent chunk-wise through a TCP stream or CoAP blocks.
*/
#ifndef COAP_MAX_CHUNK_SIZE
#ifdef REST_MAX_CHUNK_SIZE
#define COAP_MAX_CHUNK_SIZE REST_MAX_CHUNK_SIZE
#else /* REST_MAX_CHUNK_SIZE */
#define COAP_MAX_CHUNK_SIZE 64
#endif /* REST_MAX_CHUNK_SIZE */
#endif /* COAP_MAX_CHUNK_SIZE */
/* Define REST_MAX_CHUNK_SIZE for backward compatibility */
#ifndef REST_MAX_CHUNK_SIZE
#define REST_MAX_CHUNK_SIZE COAP_MAX_CHUNK_SIZE
#endif /* REST_MAX_CHUNK_SIZE */
/* Features that can be disabled to achieve smaller memory footprint */
#ifndef COAP_LINK_FORMAT_FILTERING
@ -78,4 +103,5 @@
#define COAP_OBSERVE_REFRESH_INTERVAL 20
#endif /* COAP_OBSERVE_REFRESH_INTERVAL */
#endif /* ER_COAP_CONF_H_ */
#endif /* COAP_CONF_H_ */
/** @} */

View File

@ -36,10 +36,16 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#ifndef ER_COAP_CONSTANTS_H_
#define ER_COAP_CONSTANTS_H_
/**
* \addtogroup coap
* @{
*/
#ifndef COAP_CONSTANTS_H_
#define COAP_CONSTANTS_H_
#define COAP_DEFAULT_PORT 5683
#define COAP_DEFAULT_SECURE_PORT 5684
#define COAP_DEFAULT_MAX_AGE 60
#define COAP_RESPONSE_TIMEOUT 3
@ -163,4 +169,24 @@ typedef enum {
APPLICATION_X_OBIX_BINARY = 51
} coap_content_format_t;
#endif /* ER_COAP_CONSTANTS_H_ */
/**
* Resource flags for allowed methods and special functionalities.
*/
typedef enum {
NO_FLAGS = 0,
/* methods to handle */
METHOD_GET = (1 << 0),
METHOD_POST = (1 << 1),
METHOD_PUT = (1 << 2),
METHOD_DELETE = (1 << 3),
/* special flags */
HAS_SUB_RESOURCES = (1 << 4),
IS_SEPARATE = (1 << 5),
IS_OBSERVABLE = (1 << 6),
IS_PERIODIC = (1 << 7)
} coap_resource_flags_t;
#endif /* COAP_CONSTANTS_H_ */
/** @} */

View File

@ -0,0 +1,147 @@
/*
* Copyright (c) 2016-2018, SICS, Swedish ICT AB.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/**
* \file
* API to address CoAP endpoints
* \author
* Niclas Finne <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
/**
* \addtogroup coap-transport
* @{
*/
#ifndef COAP_ENDPOINT_H_
#define COAP_ENDPOINT_H_
#include "contiki.h"
#include <stdlib.h>
#ifndef COAP_ENDPOINT_CUSTOM
#include "net/ipv6/uip.h"
typedef struct {
uip_ipaddr_t ipaddr;
uint16_t port;
uint8_t secure;
} coap_endpoint_t;
#endif /* COAP_ENDPOINT_CUSTOM */
/**
* \brief Copy a CoAP endpoint from one memory area to another.
*
* \param dest A pointer to a CoAP endpoint to copy to.
* \param src A pointer to a CoAP endpoint to copy from.
*/
void coap_endpoint_copy(coap_endpoint_t *dest, const coap_endpoint_t *src);
/**
* \brief Compare two CoAP endpoints.
*
* \param e1 A pointer to the first CoAP endpoint.
* \param e2 A pointer to the second CoAP endpoint.
* \return Non-zero if the endpoints are identical and zero otherwise.
*/
int coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2);
/**
* \brief Print a CoAP endpoint via the logging module.
*
* \param ep A pointer to the CoAP endpoint to log.
*/
void coap_endpoint_log(const coap_endpoint_t *ep);
/**
* \brief Print a CoAP endpoint.
*
* \param ep A pointer to the CoAP endpoint to print.
*/
void coap_endpoint_print(const coap_endpoint_t *ep);
/**
* \brief Print a CoAP endpoint to a string. The output is always
* null-terminated unless size is zero.
*
* \param str The string to write to.
* \param size The max number of characters to write.
* \param ep A pointer to the CoAP endpoint to print.
* \return Returns the number of characters needed for the output
* excluding the ending null-terminator or negative if an
* error occurred.
*/
int coap_endpoint_snprint(char *str, size_t size,
const coap_endpoint_t *ep);
/**
* \brief Parse a CoAP endpoint.
*
* \param text The string to parse.
* \param size The max number of characters in the string.
* \param ep A pointer to the CoAP endpoint to write to.
* \return Returns non-zero if the endpoint was successfully parsed and
* zero otherwise.
*/
int coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep);
/**
* \brief Check if a CoAP endpoint is secure (encrypted).
*
* \param ep A pointer to a CoAP endpoint.
* \return Returns non-zero if the endpoint is secure and zero otherwise.
*/
int coap_endpoint_is_secure(const coap_endpoint_t *ep);
/**
* \brief Check if a CoAP endpoint is connected.
*
* \param ep A pointer to a CoAP endpoint.
* \return Returns non-zero if the endpoint is connected and zero otherwise.
*/
int coap_endpoint_is_connected(const coap_endpoint_t *ep);
/**
* \brief Request a connection to a CoAP endpoint.
*
* \param ep A pointer to a CoAP endpoint.
* \return Returns zero if an error occured and non-zero otherwise.
*/
int coap_endpoint_connect(coap_endpoint_t *ep);
/**
* \brief Request that any connection to a CoAP endpoint is discontinued.
*
* \param ep A pointer to a CoAP endpoint.
*/
void coap_endpoint_disconnect(coap_endpoint_t *ep);
#endif /* COAP_ENDPOINT_H_ */
/** @} */

View File

@ -31,490 +31,484 @@
/**
* \file
* CoAP implementation for the REST Engine.
* CoAP implementation Engine.
* \author
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
/**
* \addtogroup coap
* @{
*/
#include "coap-engine.h"
#include "sys/cc.h"
#include "lib/list.h"
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include "coap-engine.h"
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#define PRINTLLADDR(addr)
#endif
/* Log configuration */
#include "coap-log.h"
#define LOG_MODULE "coap-engine"
#define LOG_LEVEL LOG_LEVEL_COAP
PROCESS(coap_engine, "CoAP Engine");
static void process_callback(coap_timer_t *t);
/*
* To be called by HTTP/COAP server as a callback function when a new service
* request appears. This function dispatches the corresponding CoAP service.
*/
static int invoke_coap_resource_service(coap_message_t *request,
coap_message_t *response,
uint8_t *buffer, uint16_t buffer_size,
int32_t *offset);
/*---------------------------------------------------------------------------*/
/*- Variables ---------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static service_callback_t service_cbk = NULL;
LIST(coap_handlers);
LIST(coap_resource_services);
LIST(coap_resource_periodic_services);
static uint8_t is_initialized = 0;
/*---------------------------------------------------------------------------*/
/*- Internal API ------------------------------------------------------------*/
/*- CoAP service handlers---------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static int
coap_receive(void)
void
coap_add_handler(coap_handler_t *handler)
{
erbium_status_code = NO_ERROR;
list_add(coap_handlers, handler);
}
/*---------------------------------------------------------------------------*/
void
coap_remove_handler(coap_handler_t *handler)
{
list_remove(coap_handlers, handler);
}
/*---------------------------------------------------------------------------*/
coap_handler_status_t
coap_call_handlers(coap_message_t *request, coap_message_t *response,
uint8_t *buffer, uint16_t buffer_size, int32_t *offset)
{
coap_handler_status_t status;
coap_handler_t *r;
for(r = list_head(coap_handlers); r != NULL; r = r->next) {
if(r->handler) {
status = r->handler(request, response, buffer, buffer_size, offset);
if(status != COAP_HANDLER_STATUS_CONTINUE) {
/* Request handled. */
PRINTF("handle_incoming_data(): received uip_datalen=%u \n",
(uint16_t)uip_datalen());
/* static declaration reduces stack peaks and program code size */
static coap_packet_t message[1]; /* this way the packet can be treated as pointer as usual */
static coap_packet_t response[1];
static coap_transaction_t *transaction = NULL;
if(uip_newdata()) {
PRINTF("receiving UDP datagram from: ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF(":%u\n Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport),
uip_datalen());
erbium_status_code =
coap_parse_message(message, uip_appdata, uip_datalen());
if(erbium_status_code == NO_ERROR) {
/*TODO duplicates suppression, if required by application */
PRINTF(" Parsed: v %u, t %u, tkl %u, c %u, mid %u\n", message->version,
message->type, message->token_len, message->code, message->mid);
PRINTF(" URL: %.*s\n", message->uri_path_len, message->uri_path);
PRINTF(" Payload: %.*s\n", message->payload_len, message->payload);
/* handle requests */
if(message->code >= COAP_GET && message->code <= COAP_DELETE) {
/* use transaction buffer for response to confirmable request */
if((transaction =
coap_new_transaction(message->mid, &UIP_IP_BUF->srcipaddr,
UIP_UDP_BUF->srcport))) {
uint32_t block_num = 0;
uint16_t block_size = COAP_MAX_BLOCK_SIZE;
uint32_t block_offset = 0;
int32_t new_offset = 0;
/* prepare response */
if(message->type == COAP_TYPE_CON) {
/* reliable CON requests are answered with an ACK */
coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05,
message->mid);
} else {
/* unreliable NON requests are answered with a NON as well */
coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05,
coap_get_mid());
/* mirror token */
} if(message->token_len) {
coap_set_token(response, message->token, message->token_len);
/* get offset for blockwise transfers */
}
if(coap_get_header_block2
(message, &block_num, NULL, &block_size, &block_offset)) {
PRINTF("Blockwise: block request %lu (%u/%u) @ %lu bytes\n",
block_num, block_size, COAP_MAX_BLOCK_SIZE, block_offset);
block_size = MIN(block_size, COAP_MAX_BLOCK_SIZE);
new_offset = block_offset;
}
/* invoke resource handler */
if(service_cbk) {
/* call REST framework and check if found and allowed */
if(service_cbk
(message, response, transaction->packet + COAP_MAX_HEADER_SIZE,
block_size, &new_offset)) {
if(erbium_status_code == NO_ERROR) {
/* TODO coap_handle_blockwise(request, response, start_offset, end_offset); */
/* resource is unaware of Block1 */
if(IS_OPTION(message, COAP_OPTION_BLOCK1)
&& response->code < BAD_REQUEST_4_00
&& !IS_OPTION(response, COAP_OPTION_BLOCK1)) {
PRINTF("Block1 NOT IMPLEMENTED\n");
erbium_status_code = NOT_IMPLEMENTED_5_01;
coap_error_message = "NoBlock1Support";
/* client requested Block2 transfer */
} else if(IS_OPTION(message, COAP_OPTION_BLOCK2)) {
/* unchanged new_offset indicates that resource is unaware of blockwise transfer */
if(new_offset == block_offset) {
PRINTF
("Blockwise: unaware resource with payload length %u/%u\n",
response->payload_len, block_size);
if(block_offset >= response->payload_len) {
PRINTF
("handle_incoming_data(): block_offset >= response->payload_len\n");
response->code = BAD_OPTION_4_02;
coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */
} else {
coap_set_header_block2(response, block_num,
response->payload_len -
block_offset > block_size,
block_size);
coap_set_payload(response,
response->payload + block_offset,
MIN(response->payload_len -
block_offset, block_size));
} /* if(valid offset) */
/* resource provides chunk-wise data */
} else {
PRINTF("Blockwise: blockwise resource, new offset %ld\n",
new_offset);
coap_set_header_block2(response, block_num,
new_offset != -1
|| response->payload_len >
block_size, block_size);
if(response->payload_len > block_size) {
coap_set_payload(response, response->payload,
block_size);
}
} /* if(resource aware of blockwise) */
/* Resource requested Block2 transfer */
} else if(new_offset != 0) {
PRINTF
("Blockwise: no block option for blockwise resource, using block size %u\n",
COAP_MAX_BLOCK_SIZE);
coap_set_header_block2(response, 0, new_offset != -1,
COAP_MAX_BLOCK_SIZE);
coap_set_payload(response, response->payload,
MIN(response->payload_len,
COAP_MAX_BLOCK_SIZE));
} /* blockwise transfer handling */
} /* no errors/hooks */
/* successful service callback */
/* serialize response */
}
if(erbium_status_code == NO_ERROR) {
if((transaction->packet_len = coap_serialize_message(response,
transaction->
packet)) ==
0) {
erbium_status_code = PACKET_SERIALIZATION_ERROR;
}
}
} else {
erbium_status_code = NOT_IMPLEMENTED_5_01;
coap_error_message = "NoServiceCallbck"; /* no 'a' to fit into 16 bytes */
} /* if(service callback) */
} else {
erbium_status_code = SERVICE_UNAVAILABLE_5_03;
coap_error_message = "NoFreeTraBuffer";
} /* if(transaction buffer) */
/* handle responses */
} else {
if(message->type == COAP_TYPE_CON && message->code == 0) {
PRINTF("Received Ping\n");
erbium_status_code = PING_RESPONSE;
} else if(message->type == COAP_TYPE_ACK) {
/* transactions are closed through lookup below */
PRINTF("Received ACK\n");
} else if(message->type == COAP_TYPE_RST) {
PRINTF("Received RST\n");
/* cancel possible subscriptions */
coap_remove_observer_by_mid(&UIP_IP_BUF->srcipaddr,
UIP_UDP_BUF->srcport, message->mid);
/* Check response code before doing observe! */
if(request->code == COAP_GET) {
coap_observe_handler(NULL, request, response);
}
if((transaction = coap_get_transaction_by_mid(message->mid))) {
/* free transaction memory before callback, as it may create a new transaction */
restful_response_handler callback = transaction->callback;
void *callback_data = transaction->callback_data;
coap_clear_transaction(transaction);
/* check if someone registered for the response */
if(callback) {
callback(callback_data, message);
}
}
/* if(ACKed transaction) */
transaction = NULL;
#if COAP_OBSERVE_CLIENT
/* if observe notification */
if((message->type == COAP_TYPE_CON || message->type == COAP_TYPE_NON)
&& IS_OPTION(message, COAP_OPTION_OBSERVE)) {
PRINTF("Observe [%u]\n", message->observe);
coap_handle_notification(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport,
message);
}
#endif /* COAP_OBSERVE_CLIENT */
} /* request or response */
} /* parsed correctly */
/* if(parsed correctly) */
if(erbium_status_code == NO_ERROR) {
if(transaction) {
coap_send_transaction(transaction);
return status;
}
} else if(erbium_status_code == MANUAL_RESPONSE) {
PRINTF("Clearing transaction for manual response");
coap_clear_transaction(transaction);
} else {
coap_message_type_t reply_type = COAP_TYPE_ACK;
PRINTF("ERROR %u: %s\n", erbium_status_code, coap_error_message);
coap_clear_transaction(transaction);
if(erbium_status_code == PING_RESPONSE) {
erbium_status_code = 0;
reply_type = COAP_TYPE_RST;
} else if(erbium_status_code >= 192) {
/* set to sendable error code */
erbium_status_code = INTERNAL_SERVER_ERROR_5_00;
/* reuse input buffer for error message */
}
coap_init_message(message, reply_type, erbium_status_code,
message->mid);
coap_set_payload(message, coap_error_message,
strlen(coap_error_message));
coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport,
uip_appdata, coap_serialize_message(message,
uip_appdata));
}
}
return COAP_HANDLER_STATUS_CONTINUE;
}
/*---------------------------------------------------------------------------*/
static CC_INLINE coap_handler_status_t
call_service(coap_message_t *request, coap_message_t *response,
uint8_t *buffer, uint16_t buffer_size, int32_t *offset)
{
coap_handler_status_t status;
status = coap_call_handlers(request, response, buffer, buffer_size, offset);
if(status != COAP_HANDLER_STATUS_CONTINUE) {
return status;
}
status = invoke_coap_resource_service(request, response, buffer, buffer_size, offset);
if(status != COAP_HANDLER_STATUS_CONTINUE) {
return status;
}
/* if(new data) */
return erbium_status_code;
}
/*---------------------------------------------------------------------------*/
void
coap_init_engine(void)
{
process_start(&coap_engine, NULL);
}
/*---------------------------------------------------------------------------*/
void
coap_set_service_callback(service_callback_t callback)
{
service_cbk = callback;
}
/*---------------------------------------------------------------------------*/
rest_resource_flags_t
coap_get_rest_method(void *packet)
{
return (rest_resource_flags_t)(1 <<
(((coap_packet_t *)packet)->code - 1));
coap_set_status_code(response, NOT_FOUND_4_04);
return COAP_HANDLER_STATUS_CONTINUE;
}
/*---------------------------------------------------------------------------*/
/*- Server Part -------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* the discover resource is automatically included for CoAP */
extern resource_t res_well_known_core;
#ifdef WITH_DTLS
extern resource_t res_dtls;
#endif
extern coap_resource_t res_well_known_core;
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(coap_engine, ev, data)
/*- Internal API ------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
int
coap_receive(const coap_endpoint_t *src,
uint8_t *payload, uint16_t payload_length)
{
PROCESS_BEGIN();
PRINTF("Starting %s receiver...\n", coap_rest_implementation.name);
/* static declaration reduces stack peaks and program code size */
static coap_message_t message[1]; /* this way the message can be treated as pointer as usual */
static coap_message_t response[1];
coap_transaction_t *transaction = NULL;
coap_handler_status_t status;
rest_activate_resource(&res_well_known_core, ".well-known/core");
coap_status_code = coap_parse_message(message, payload, payload_length);
coap_set_src_endpoint(message, src);
coap_register_as_transaction_handler();
coap_init_connection(SERVER_LISTEN_PORT);
if(coap_status_code == NO_ERROR) {
while(1) {
PROCESS_YIELD();
/*TODO duplicates suppression, if required by application */
if(ev == tcpip_event) {
coap_receive();
} else if(ev == PROCESS_EVENT_TIMER) {
/* retransmissions are handled here */
coap_check_transactions();
LOG_DBG(" Parsed: v %u, t %u, tkl %u, c %u, mid %u\n", message->version,
message->type, message->token_len, message->code, message->mid);
LOG_DBG(" URL:");
LOG_DBG_COAP_STRING(message->uri_path, message->uri_path_len);
LOG_DBG_("\n");
LOG_DBG(" Payload: ");
LOG_DBG_COAP_STRING((const char *)message->payload, message->payload_len);
LOG_DBG_("\n");
/* handle requests */
if(message->code >= COAP_GET && message->code <= COAP_DELETE) {
/* use transaction buffer for response to confirmable request */
if((transaction = coap_new_transaction(message->mid, src))) {
uint32_t block_num = 0;
uint16_t block_size = COAP_MAX_BLOCK_SIZE;
uint32_t block_offset = 0;
int32_t new_offset = 0;
/* prepare response */
if(message->type == COAP_TYPE_CON) {
/* reliable CON requests are answered with an ACK */
coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05,
message->mid);
} else {
/* unreliable NON requests are answered with a NON as well */
coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05,
coap_get_mid());
/* mirror token */
}
if(message->token_len) {
coap_set_token(response, message->token, message->token_len);
/* get offset for blockwise transfers */
}
if(coap_get_header_block2
(message, &block_num, NULL, &block_size, &block_offset)) {
LOG_DBG("Blockwise: block request %"PRIu32" (%u/%u) @ %"PRIu32" bytes\n",
block_num, block_size, COAP_MAX_BLOCK_SIZE, block_offset);
block_size = MIN(block_size, COAP_MAX_BLOCK_SIZE);
new_offset = block_offset;
}
/* call CoAP framework and check if found and allowed */
status = call_service(message, response,
transaction->message + COAP_MAX_HEADER_SIZE,
block_size, &new_offset);
if(status != COAP_HANDLER_STATUS_CONTINUE) {
if(coap_status_code == NO_ERROR) {
/* TODO coap_handle_blockwise(request, response, start_offset, end_offset); */
/* resource is unaware of Block1 */
if(coap_is_option(message, COAP_OPTION_BLOCK1)
&& response->code < BAD_REQUEST_4_00
&& !coap_is_option(response, COAP_OPTION_BLOCK1)) {
LOG_DBG("Block1 NOT IMPLEMENTED\n");
coap_status_code = NOT_IMPLEMENTED_5_01;
coap_error_message = "NoBlock1Support";
/* client requested Block2 transfer */
} else if(coap_is_option(message, COAP_OPTION_BLOCK2)) {
/* unchanged new_offset indicates that resource is unaware of blockwise transfer */
if(new_offset == block_offset) {
LOG_DBG("Blockwise: unaware resource with payload length %u/%u\n",
response->payload_len, block_size);
if(block_offset >= response->payload_len) {
LOG_DBG("handle_incoming_data(): block_offset >= response->payload_len\n");
response->code = BAD_OPTION_4_02;
coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */
} else {
coap_set_header_block2(response, block_num,
response->payload_len -
block_offset > block_size,
block_size);
coap_set_payload(response,
response->payload + block_offset,
MIN(response->payload_len -
block_offset, block_size));
} /* if(valid offset) */
/* resource provides chunk-wise data */
} else {
LOG_DBG("Blockwise: blockwise resource, new offset %"PRId32"\n",
new_offset);
coap_set_header_block2(response, block_num,
new_offset != -1
|| response->payload_len >
block_size, block_size);
if(response->payload_len > block_size) {
coap_set_payload(response, response->payload,
block_size);
}
} /* if(resource aware of blockwise) */
/* Resource requested Block2 transfer */
} else if(new_offset != 0) {
LOG_DBG("Blockwise: no block option for blockwise resource, using block size %u\n",
COAP_MAX_BLOCK_SIZE);
coap_set_header_block2(response, 0, new_offset != -1,
COAP_MAX_BLOCK_SIZE);
coap_set_payload(response, response->payload,
MIN(response->payload_len,
COAP_MAX_BLOCK_SIZE));
} /* blockwise transfer handling */
} /* no errors/hooks */
/* successful service callback */
/* serialize response */
}
if(coap_status_code == NO_ERROR) {
if((transaction->message_len = coap_serialize_message(response,
transaction->
message)) ==
0) {
coap_status_code = PACKET_SERIALIZATION_ERROR;
}
}
} else {
coap_status_code = SERVICE_UNAVAILABLE_5_03;
coap_error_message = "NoFreeTraBuffer";
} /* if(transaction buffer) */
/* handle responses */
} else {
if(message->type == COAP_TYPE_CON && message->code == 0) {
LOG_INFO("Received Ping\n");
coap_status_code = PING_RESPONSE;
} else if(message->type == COAP_TYPE_ACK) {
/* transactions are closed through lookup below */
LOG_DBG("Received ACK\n");
} else if(message->type == COAP_TYPE_RST) {
LOG_INFO("Received RST\n");
/* cancel possible subscriptions */
coap_remove_observer_by_mid(src, message->mid);
}
if((transaction = coap_get_transaction_by_mid(message->mid))) {
/* free transaction memory before callback, as it may create a new transaction */
coap_resource_response_handler_t callback = transaction->callback;
void *callback_data = transaction->callback_data;
coap_clear_transaction(transaction);
/* check if someone registered for the response */
if(callback) {
callback(callback_data, message);
}
}
/* if(ACKed transaction) */
transaction = NULL;
#if COAP_OBSERVE_CLIENT
/* if observe notification */
if((message->type == COAP_TYPE_CON || message->type == COAP_TYPE_NON)
&& coap_is_option(message, COAP_OPTION_OBSERVE)) {
LOG_DBG("Observe [%"PRId32"]\n", message->observe);
coap_handle_notification(src, message);
}
#endif /* COAP_OBSERVE_CLIENT */
} /* request or response */
} /* parsed correctly */
/* if(parsed correctly) */
if(coap_status_code == NO_ERROR) {
if(transaction) {
coap_send_transaction(transaction);
}
} /* while (1) */
} else if(coap_status_code == MANUAL_RESPONSE) {
LOG_DBG("Clearing transaction for manual response");
coap_clear_transaction(transaction);
} else {
coap_message_type_t reply_type = COAP_TYPE_ACK;
PROCESS_END();
LOG_WARN("ERROR %u: %s\n", coap_status_code, coap_error_message);
coap_clear_transaction(transaction);
if(coap_status_code == PING_RESPONSE) {
coap_status_code = 0;
reply_type = COAP_TYPE_RST;
} else if(coap_status_code >= 192) {
/* set to sendable error code */
coap_status_code = INTERNAL_SERVER_ERROR_5_00;
/* reuse input buffer for error message */
}
coap_init_message(message, reply_type, coap_status_code,
message->mid);
coap_set_payload(message, coap_error_message,
strlen(coap_error_message));
coap_sendto(src, payload, coap_serialize_message(message, payload));
}
/* if(new data) */
return coap_status_code;
}
/*---------------------------------------------------------------------------*/
/*- Client Part -------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void
coap_blocking_request_callback(void *callback_data, void *response)
coap_engine_init(void)
{
struct request_state_t *state = (struct request_state_t *)callback_data;
state->response = (coap_packet_t *)response;
process_poll(state->process);
}
/*---------------------------------------------------------------------------*/
PT_THREAD(coap_blocking_request
(struct request_state_t *state, process_event_t ev,
uip_ipaddr_t *remote_ipaddr, uint16_t remote_port,
coap_packet_t *request,
blocking_response_handler request_callback))
{
PT_BEGIN(&state->pt);
static uint8_t more;
static uint32_t res_block;
static uint8_t block_error;
state->block_num = 0;
state->response = NULL;
state->process = PROCESS_CURRENT();
more = 0;
res_block = 0;
block_error = 0;
do {
request->mid = coap_get_mid();
if((state->transaction = coap_new_transaction(request->mid, remote_ipaddr,
remote_port))) {
state->transaction->callback = coap_blocking_request_callback;
state->transaction->callback_data = state;
if(state->block_num > 0) {
coap_set_header_block2(request, state->block_num, 0,
REST_MAX_CHUNK_SIZE);
}
state->transaction->packet_len = coap_serialize_message(request,
state->
transaction->
packet);
coap_send_transaction(state->transaction);
PRINTF("Requested #%lu (MID %u)\n", state->block_num, request->mid);
PT_YIELD_UNTIL(&state->pt, ev == PROCESS_EVENT_POLL);
if(!state->response) {
PRINTF("Server not responding\n");
PT_EXIT(&state->pt);
}
coap_get_header_block2(state->response, &res_block, &more, NULL, NULL);
PRINTF("Received #%lu%s (%u bytes)\n", res_block, more ? "+" : "",
state->response->payload_len);
if(res_block == state->block_num) {
request_callback(state->response);
++(state->block_num);
} else {
PRINTF("WRONG BLOCK %lu/%lu\n", res_block, state->block_num);
++block_error;
}
} else {
PRINTF("Could not allocate transaction buffer");
PT_EXIT(&state->pt);
}
} while(more && block_error < COAP_MAX_ATTEMPTS);
PT_END(&state->pt);
}
/*---------------------------------------------------------------------------*/
/*- REST Engine Interface ---------------------------------------------------*/
/*---------------------------------------------------------------------------*/
const struct rest_implementation coap_rest_implementation = {
"CoAP-18",
coap_init_engine,
coap_set_service_callback,
coap_get_header_uri_path,
coap_get_rest_method,
coap_set_status_code,
coap_get_header_content_format,
coap_set_header_content_format,
coap_get_header_accept,
coap_get_header_size2,
coap_set_header_size2,
coap_get_header_max_age,
coap_set_header_max_age,
coap_set_header_etag,
coap_get_header_if_match,
coap_get_header_if_none_match,
coap_get_header_uri_host,
coap_set_header_location_path,
coap_get_payload,
coap_set_payload,
coap_get_header_uri_query,
coap_get_query_variable,
coap_get_post_variable,
coap_notify_observers,
coap_observe_handler,
{
CONTENT_2_05,
CREATED_2_01,
CHANGED_2_04,
DELETED_2_02,
VALID_2_03,
BAD_REQUEST_4_00,
UNAUTHORIZED_4_01,
BAD_OPTION_4_02,
FORBIDDEN_4_03,
NOT_FOUND_4_04,
METHOD_NOT_ALLOWED_4_05,
NOT_ACCEPTABLE_4_06,
REQUEST_ENTITY_TOO_LARGE_4_13,
UNSUPPORTED_MEDIA_TYPE_4_15,
INTERNAL_SERVER_ERROR_5_00,
NOT_IMPLEMENTED_5_01,
BAD_GATEWAY_5_02,
SERVICE_UNAVAILABLE_5_03,
GATEWAY_TIMEOUT_5_04,
PROXYING_NOT_SUPPORTED_5_05
},
{
TEXT_PLAIN,
TEXT_XML,
TEXT_CSV,
TEXT_HTML,
IMAGE_GIF,
IMAGE_JPEG,
IMAGE_PNG,
IMAGE_TIFF,
AUDIO_RAW,
VIDEO_RAW,
APPLICATION_LINK_FORMAT,
APPLICATION_XML,
APPLICATION_OCTET_STREAM,
APPLICATION_RDF_XML,
APPLICATION_SOAP_XML,
APPLICATION_ATOM_XML,
APPLICATION_XMPP_XML,
APPLICATION_EXI,
APPLICATION_FASTINFOSET,
APPLICATION_SOAP_FASTINFOSET,
APPLICATION_JSON,
APPLICATION_X_OBIX_BINARY
/* avoid initializing twice */
if(is_initialized) {
LOG_DBG("already running - double initialization?\n");
return;
}
};
is_initialized = 1;
LOG_INFO("Starting CoAP engine...\n");
list_init(coap_handlers);
list_init(coap_resource_services);
list_init(coap_resource_periodic_services);
coap_activate_resource(&res_well_known_core, ".well-known/core");
coap_transport_init();
coap_init_connection();
}
/*---------------------------------------------------------------------------*/
/**
* \brief Makes a resource available under the given URI path
* \param resource A pointer to a resource implementation
* \param path The URI path string for this resource
*
* The resource implementation must be imported first using the
* extern keyword. The build system takes care of compiling every
* *.c file in the ./resources/ sub-directory (see example Makefile).
*/
void
coap_activate_resource(coap_resource_t *resource, const char *path)
{
coap_periodic_resource_t *periodic;
resource->url = path;
list_add(coap_resource_services, resource);
LOG_INFO("Activating: %s\n", resource->url);
/* Only add periodic resources with a periodic_handler and a period > 0. */
if(resource->flags & IS_PERIODIC && resource->periodic
&& resource->periodic->periodic_handler
&& resource->periodic->period) {
LOG_DBG("Periodic resource: %p (%s)\n", resource->periodic, path);
list_add(coap_resource_periodic_services, resource->periodic);
periodic = resource->periodic;
coap_timer_set_callback(&periodic->periodic_timer, process_callback);
coap_timer_set_user_data(&periodic->periodic_timer, resource);
coap_timer_set(&periodic->periodic_timer, periodic->period);
}
}
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*- Internal API ------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
coap_resource_t *
coap_get_first_resource(void)
{
return list_head(coap_resource_services);
}
/*---------------------------------------------------------------------------*/
coap_resource_t *
coap_get_next_resource(coap_resource_t *resource)
{
return list_item_next(resource);
}
/*---------------------------------------------------------------------------*/
static int
invoke_coap_resource_service(coap_message_t *request, coap_message_t *response,
uint8_t *buffer, uint16_t buffer_size,
int32_t *offset)
{
uint8_t found = 0;
uint8_t allowed = 1;
coap_resource_t *resource = NULL;
const char *url = NULL;
int url_len, res_url_len;
url_len = coap_get_header_uri_path(request, &url);
for(resource = list_head(coap_resource_services);
resource; resource = resource->next) {
/* if the web service handles that kind of requests and urls matches */
res_url_len = strlen(resource->url);
if((url_len == res_url_len
|| (url_len > res_url_len
&& (resource->flags & HAS_SUB_RESOURCES)
&& url[res_url_len] == '/'))
&& strncmp(resource->url, url, res_url_len) == 0) {
coap_resource_flags_t method = coap_get_method_type(request);
found = 1;
LOG_INFO("/%s, method %u, resource->flags %u\n", resource->url,
(uint16_t)method, resource->flags);
if((method & METHOD_GET) && resource->get_handler != NULL) {
/* call handler function */
resource->get_handler(request, response, buffer, buffer_size, offset);
} else if((method & METHOD_POST) && resource->post_handler != NULL) {
/* call handler function */
resource->post_handler(request, response, buffer, buffer_size,
offset);
} else if((method & METHOD_PUT) && resource->put_handler != NULL) {
/* call handler function */
resource->put_handler(request, response, buffer, buffer_size, offset);
} else if((method & METHOD_DELETE) && resource->delete_handler != NULL) {
/* call handler function */
resource->delete_handler(request, response, buffer, buffer_size,
offset);
} else {
allowed = 0;
coap_set_status_code(response, METHOD_NOT_ALLOWED_4_05);
}
break;
}
}
if(!found) {
coap_set_status_code(response, NOT_FOUND_4_04);
} else if(allowed) {
/* final handler for special flags */
if(resource->flags & IS_OBSERVABLE) {
coap_observe_handler(resource, request, response);
}
}
return found & allowed;
}
/*---------------------------------------------------------------------------*/
/* This callback occurs when t is expired */
static void
process_callback(coap_timer_t *t)
{
coap_resource_t *resource;
resource = coap_timer_get_user_data(t);
if(resource != NULL && (resource->flags & IS_PERIODIC)
&& resource->periodic != NULL && resource->periodic->period) {
LOG_DBG("Periodic: timer expired for /%s (period: %"PRIu32")\n",
resource->url, resource->periodic->period);
if(!is_initialized) {
/* CoAP has not yet been initialized. */
} else if(resource->periodic->periodic_handler) {
/* Call the periodic_handler function. */
resource->periodic->periodic_handler();
}
coap_timer_set(t, resource->periodic->period);
}
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -31,56 +31,148 @@
/**
* \file
* CoAP implementation for the REST Engine.
* CoAP engine implementation.
* \author
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#ifndef ER_COAP_ENGINE_H_
#define ER_COAP_ENGINE_H_
/**
* \addtogroup coap
* @{
*/
#ifndef COAP_ENGINE_H_
#define COAP_ENGINE_H_
typedef struct coap_resource_s coap_resource_t;
typedef struct coap_periodic_resource_s coap_periodic_resource_t;
#include "pt.h"
#include "coap.h"
#include "coap-timer.h"
typedef enum {
COAP_HANDLER_STATUS_CONTINUE,
COAP_HANDLER_STATUS_PROCESSED
} coap_handler_status_t;
typedef coap_handler_status_t
(* coap_handler_callback_t)(coap_message_t *request,
coap_message_t *response,
uint8_t *buffer, uint16_t buffer_size,
int32_t *offset);
typedef struct coap_handler coap_handler_t;
struct coap_handler {
coap_handler_t *next;
coap_handler_callback_t handler;
};
#define COAP_HANDLER(name, handler) \
coap_handler_t name = { NULL, handler }
void coap_add_handler(coap_handler_t *handler);
void coap_remove_handler(coap_handler_t *handler);
void coap_engine_init(void);
int coap_receive(const coap_endpoint_t *src,
uint8_t *payload, uint16_t payload_length);
coap_handler_status_t coap_call_handlers(coap_message_t *request,
coap_message_t *response,
uint8_t *buffer,
uint16_t buffer_size,
int32_t *offset);
/*---------------------------------------------------------------------------*/
/* signatures of handler functions */
typedef void (* coap_resource_handler_t)(coap_message_t *request,
coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size,
int32_t *offset);
typedef void (* coap_resource_periodic_handler_t)(void);
typedef void (* coap_resource_response_handler_t)(void *data,
coap_message_t *response);
typedef void (* coap_resource_trigger_handler_t)(void);
/* data structure representing a resource in CoAP */
struct coap_resource_s {
coap_resource_t *next; /* for LIST, points to next resource defined */
const char *url; /*handled URL */
coap_resource_flags_t flags; /* handled CoAP methods */
const char *attributes; /* link-format attributes */
coap_resource_handler_t get_handler; /* handler function */
coap_resource_handler_t post_handler; /* handler function */
coap_resource_handler_t put_handler; /* handler function */
coap_resource_handler_t delete_handler; /* handler function */
union {
coap_periodic_resource_t *periodic; /* special data depending on flags */
coap_resource_trigger_handler_t trigger;
coap_resource_trigger_handler_t resume;
};
};
struct coap_periodic_resource_s {
uint32_t period;
coap_timer_t periodic_timer;
const coap_resource_periodic_handler_t periodic_handler;
};
/*
* Macro to define a CoAP resource.
* Resources are statically defined for the sake of efficiency and better memory management.
*/
#define RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \
coap_resource_t name = { NULL, NULL, NO_FLAGS, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } }
#define PARENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \
coap_resource_t name = { NULL, NULL, HAS_SUB_RESOURCES, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } }
#define SEPARATE_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, resume_handler) \
coap_resource_t name = { NULL, NULL, IS_SEPARATE, attributes, get_handler, post_handler, put_handler, delete_handler, { .resume = resume_handler } }
#define EVENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, event_handler) \
coap_resource_t name = { NULL, NULL, IS_OBSERVABLE, attributes, get_handler, post_handler, put_handler, delete_handler, { .trigger = event_handler } }
/*
* Macro to define a periodic resource.
* The corresponding [name]_periodic_handler() function will be called every period.
* For instance polling a sensor and publishing a changed value to subscribed clients would be done there.
*/
#define PERIODIC_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, period, periodic_handler) \
static coap_periodic_resource_t periodic_##name = { period, { 0 }, periodic_handler }; \
coap_resource_t name = { NULL, NULL, IS_OBSERVABLE | IS_PERIODIC, attributes, get_handler, post_handler, put_handler, delete_handler, { .periodic = &periodic_##name } }
/*---------------------------------------------------------------------------*/
/**
*
* \brief Resources wanted to be accessible should be activated with the following code.
* \param resource
* A CoAP resource defined through the RESOURCE macros.
* \param path
* The local URI path where to provide the resource.
*/
void coap_activate_resource(coap_resource_t *resource, const char *path);
/*---------------------------------------------------------------------------*/
/**
* \brief Returns the first of registered CoAP resources.
* \return The first registered CoAP resource or NULL if none exists.
*/
coap_resource_t *coap_get_first_resource(void);
/*---------------------------------------------------------------------------*/
/**
* \brief Returns the next registered CoAP resource.
* \return The next resource or NULL if no more exists.
*/
coap_resource_t *coap_get_next_resource(coap_resource_t *resource);
/*---------------------------------------------------------------------------*/
#include "coap-transactions.h"
#include "coap-observe.h"
#include "coap-separate.h"
#include "coap-observe-client.h"
#include "coap-transport.h"
#define SERVER_LISTEN_PORT UIP_HTONS(COAP_SERVER_PORT)
typedef coap_packet_t rest_request_t;
typedef coap_packet_t rest_response_t;
void coap_init_engine(void);
/*---------------------------------------------------------------------------*/
/*- Client Part -------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
struct request_state_t {
struct pt pt;
struct process *process;
coap_transaction_t *transaction;
coap_packet_t *response;
uint32_t block_num;
};
typedef void (*blocking_response_handler)(void *response);
PT_THREAD(coap_blocking_request
(struct request_state_t *state, process_event_t ev,
uip_ipaddr_t *remote_ipaddr, uint16_t remote_port,
coap_packet_t *request,
blocking_response_handler request_callback));
#define COAP_BLOCKING_REQUEST(server_addr, server_port, request, chunk_handler) \
{ \
static struct request_state_t request_state; \
PT_SPAWN(process_pt, &request_state.pt, \
coap_blocking_request(&request_state, ev, \
server_addr, server_port, \
request, chunk_handler) \
); \
}
/*---------------------------------------------------------------------------*/
#endif /* ER_COAP_ENGINE_H_ */
#endif /* COAP_ENGINE_H_ */
/** @} */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Yanzi Networks AB.
* Copyright (c) 2017, RISE SICS AB.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -29,61 +29,69 @@
*/
/**
* \addtogroup oma-lwm2m
* @{
*
* \file
* A simple keystore with fixed credentials.
* \author
* Niclas Finne <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
/**
* \file
* Implementation of the Contiki OMA LWM2M TLV writer
* \author
* Joakim Eriksson <joakime@sics.se>
* Niclas Finne <nfi@sics.se>
* \addtogroup coap-keystore
* @{
*/
#include "lwm2m-object.h"
#include "oma-tlv.h"
#include "coap-endpoint.h"
#include "coap-keystore.h"
#include <string.h>
#ifdef WITH_DTLS
#ifdef COAP_DTLS_PSK_DEFAULT_IDENTITY
#ifdef COAP_DTLS_PSK_DEFAULT_KEY
/*---------------------------------------------------------------------------*/
static size_t
write_boolean_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen,
int value)
static int
get_default_psk_info(const coap_endpoint_t *address_info,
coap_keystore_psk_entry_t *info)
{
return oma_tlv_write_int32(ctx->resource_id, value != 0 ? 1 : 0,
outbuf, outlen);
if(info != NULL) {
if(info->identity == NULL || info->identity_len == 0) {
/* Identity requested */
info->identity = (uint8_t *)COAP_DTLS_PSK_DEFAULT_IDENTITY;
info->identity_len = strlen(COAP_DTLS_PSK_DEFAULT_IDENTITY);
return 1;
}
if(info->identity_len != strlen(COAP_DTLS_PSK_DEFAULT_IDENTITY) ||
memcmp(info->identity, COAP_DTLS_PSK_DEFAULT_IDENTITY,
info->identity_len) != 0) {
/* Identity not matching */
return 0;
}
info->key = (uint8_t *)COAP_DTLS_PSK_DEFAULT_KEY;
info->key_len = strlen(COAP_DTLS_PSK_DEFAULT_KEY);
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
static size_t
write_int_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen,
int32_t value)
{
return oma_tlv_write_int32(ctx->resource_id, value, outbuf, outlen);
}
/*---------------------------------------------------------------------------*/
static size_t
write_float32fix_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf,
size_t outlen, int32_t value, int bits)
{
return oma_tlv_write_float32(ctx->resource_id, value, bits, outbuf, outlen);
}
/*---------------------------------------------------------------------------*/
static size_t
write_string_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen,
const char *value, size_t stringlen)
{
oma_tlv_t tlv;
tlv.type = OMA_TLV_TYPE_RESOURCE;
tlv.value = (uint8_t *) value;
tlv.length = (uint32_t) stringlen;
tlv.id = ctx->resource_id;
return oma_tlv_write(&tlv, outbuf, outlen);
}
/*---------------------------------------------------------------------------*/
const lwm2m_writer_t oma_tlv_writer = {
write_int_tlv,
write_string_tlv,
write_float32fix_tlv,
write_boolean_tlv
static const coap_keystore_t simple_key_store = {
.coap_get_psk_info = get_default_psk_info
};
/*---------------------------------------------------------------------------*/
#endif /* COAP_DTLS_PSK_DEFAULT_KEY */
#endif /* COAP_DTLS_PSK_DEFAULT_IDENTITY */
#endif /* WITH_DTLS */
/*---------------------------------------------------------------------------*/
void
coap_keystore_simple_init(void)
{
#ifdef WITH_DTLS
#ifdef COAP_DTLS_PSK_DEFAULT_IDENTITY
#ifdef COAP_DTLS_PSK_DEFAULT_KEY
coap_set_keystore(&simple_key_store);
#endif /* COAP_DTLS_PSK_DEFAULT_KEY */
#endif /* COAP_DTLS_PSK_DEFAULT_IDENTITY */
#endif /* WITH_DTLS */
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2017, RISE SICS AB.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
* A simple keystore with fixed credentials.
* \author
* Niclas Finne <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
/**
* \addtogroup coap-keystore
* @{
*/
#ifndef COAP_KEYSTORE_SIMPLE_H_
#define COAP_KEYSTORE_SIMPLE_H_
/**
* \brief Registers a simple CoAP DTLS keystore with fixed pre-shared key
* credentials.
*
* The credentials can be configured in project-conf.h as shown in the
* following example:
*
* ~~~~~~~~~~~~~~~{.c}
* #define COAP_DTLS_PSK_DEFAULT_IDENTITY "user"
* #define COAP_DTLS_PSK_DEFAULT_KEY "password"
* ~~~~~~~~~~~~~~~
*/
void coap_keystore_simple_init(void);
#endif /* COAP_KEYSTORE_SIMPLE_H_ */
/** @} */

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2017, RISE SICS
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
*/
/**
* \file
* API for CoAP keystore
* \author
* Niclas Finne <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
/**
* \addtogroup coap
* @{
*
* \defgroup coap-keystore CoAP keystore API
* @{
*
* The CoAP keystore API defines a common interface for retrieving
* authorization information for CoAP/DTLS.
*/
#ifndef COAP_KEYSTORE_H_
#define COAP_KEYSTORE_H_
#include "coap-endpoint.h"
/**
* The structure of a CoAP pre-shared key info.
*/
typedef struct {
const uint8_t *identity_hint;
uint16_t identity_hint_len;
const uint8_t *identity;
uint16_t identity_len;
const uint8_t *key;
uint16_t key_len;
} coap_keystore_psk_entry_t;
/**
* The structure of a CoAP keystore.
*
* The keystore implementation provides a function callback for each type of
* authorization supported. The API currently only specifies a function
* callback for pre-shared keys.
*/
typedef struct {
int (* coap_get_psk_info)(const coap_endpoint_t *address_info,
coap_keystore_psk_entry_t *info);
} coap_keystore_t;
/**
* \brief Set the CoAP keystore to use by CoAP.
* \param keystore A pointer to a CoAP keystore.
*/
void coap_set_keystore(const coap_keystore_t *keystore);
#endif /* COAP_KEYSTORE_H_ */
/** @} */
/** @} */

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2017, RISE SICS.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
* Log support for CoAP
* \author
* Niclas Finne <niclas.finne@ri.se>
* Joakim Eriksson <joakim.eriksson@ri.se>
*/
/**
* \addtogroup coap
* @{
*/
#include "coap-log.h"
/*---------------------------------------------------------------------------*/
void
coap_log_string(const char *text, size_t len)
{
int i;
if(text == NULL) {
LOG_OUTPUT("(NULL STR)");
return;
}
for(i = 0; i < len && *text != '\0'; i++, text++) {
LOG_OUTPUT("%c", *text);
}
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2017, RISE SICS.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
* Log support for CoAP
* \author
* Niclas Finne <niclas.finne@ri.se>
* Joakim Eriksson <joakim.eriksson@ri.se>
*/
/**
* \addtogroup coap
* @{
*/
#ifndef COAP_LOG_H_
#define COAP_LOG_H_
#include "contiki.h"
#ifdef COAP_LOG_CONF_PATH
#include COAP_LOG_CONF_PATH
#else /* COAP_LOG_CONF_PATH */
#include "sys/log.h"
#endif /* COAP_LOG_CONF_PATH */
#include "coap-endpoint.h"
/* CoAP endpoint */
#define LOG_COAP_EP(level, endpoint) do { \
if(level <= (LOG_LEVEL)) { \
coap_endpoint_log(endpoint); \
} \
} while (0)
#define LOG_ERR_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_ERR, endpoint)
#define LOG_WARN_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_WARN, endpoint)
#define LOG_INFO_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_INFO, endpoint)
#define LOG_DBG_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_DBG, endpoint)
/* CoAP strings */
#define LOG_COAP_STRING(level, text, len) do { \
if(level <= (LOG_LEVEL)) { \
coap_log_string(text, len); \
} \
} while (0)
#define LOG_ERR_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_ERR, text, len)
#define LOG_WARN_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_WARN, text, len)
#define LOG_INFO_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_INFO, text, len)
#define LOG_DBG_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_DBG, text, len)
/**
* \brief Logs a CoAP string that has a length but might not be 0-terminated.
* \param text The CoAP string
* \param len The number of characters in the CoAP string
*/
void coap_log_string(const char *text, size_t len);
#endif /* COAP_LOG_H_ */
/** @} */

View File

@ -37,57 +37,42 @@
* Daniele Alessandrelli <daniele.alessandrelli@gmail.com>
*/
#include <stdio.h>
#include <string.h>
/**
* \addtogroup coap
* @{
*/
#include "coap.h"
#include "coap-observe-client.h"
#include "sys/cc.h"
#include "lib/memb.h"
#include "lib/list.h"
#include <stdio.h>
#include <string.h>
/* Compile this code only if client-side support for CoAP Observe is required */
#if COAP_OBSERVE_CLIENT
#define DEBUG 1
#if DEBUG
#define PRINTF(...) printf(__VA_ARGS__)
#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:" \
"%02x%02x:%02x%02x:%02x%02x:%02x%02x]", \
((uint8_t *)addr)[0], ((uint8_t *)addr)[1], \
((uint8_t *)addr)[2], ((uint8_t *)addr)[3], \
((uint8_t *)addr)[4], ((uint8_t *)addr)[5], \
((uint8_t *)addr)[6], ((uint8_t *)addr)[7], \
((uint8_t *)addr)[8], ((uint8_t *)addr)[9], \
((uint8_t *)addr)[10], ((uint8_t *)addr)[11], \
((uint8_t *)addr)[12], ((uint8_t *)addr)[13], \
((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", \
(lladdr)->addr[0], (lladdr)->addr[1], \
(lladdr)->addr[2], (lladdr)->addr[3], \
(lladdr)->addr[4], (lladdr)->addr[5])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#define PRINTLLADDR(addr)
#endif
/* Log configuration */
#include "coap-log.h"
#define LOG_MODULE "coap-observe-client"
#define LOG_LEVEL LOG_LEVEL_COAP
MEMB(obs_subjects_memb, coap_observee_t, COAP_MAX_OBSERVEES);
LIST(obs_subjects_list);
/*----------------------------------------------------------------------------*/
static size_t
get_token(void *packet, const uint8_t **token)
get_token(coap_message_t *coap_pkt, const uint8_t **token)
{
coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
*token = coap_pkt->token;
return coap_pkt->token_len;
}
/*----------------------------------------------------------------------------*/
static int
set_token(void *packet, const uint8_t *token, size_t token_len)
set_token(coap_message_t *coap_pkt, const uint8_t *token, size_t token_len)
{
coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len);
memcpy(coap_pkt->token, token, coap_pkt->token_len);
@ -95,7 +80,7 @@ set_token(void *packet, const uint8_t *token, size_t token_len)
}
/*----------------------------------------------------------------------------*/
coap_observee_t *
coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port,
coap_obs_add_observee(const coap_endpoint_t *endpoint,
const uint8_t *token, size_t token_len, const char *url,
notification_callback_t notification_callback,
void *data)
@ -103,20 +88,18 @@ coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port,
coap_observee_t *o;
/* Remove existing observe relationship, if any. */
coap_obs_remove_observee_by_url(addr, port, url);
coap_obs_remove_observee_by_url(endpoint, url);
o = memb_alloc(&obs_subjects_memb);
if(o) {
o->url = url;
uip_ipaddr_copy(&o->addr, addr);
o->port = port;
coap_endpoint_copy(&o->endpoint, endpoint);
o->token_len = token_len;
memcpy(o->token, token, token_len);
/* o->last_mid = 0; */
o->notification_callback = notification_callback;
o->data = data;
/* stimer_set(&o->refresh_timer, COAP_OBSERVING_REFRESH_INTERVAL); */
PRINTF("Adding obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0],
o->token[1]);
LOG_DBG("Adding obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0],
o->token[1]);
list_add(obs_subjects_list, o);
}
@ -126,8 +109,8 @@ coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port,
void
coap_obs_remove_observee(coap_observee_t *o)
{
PRINTF("Removing obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0],
o->token[1]);
LOG_DBG("Removing obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0],
o->token[1]);
memb_free(&obs_subjects_memb, o);
list_remove(obs_subjects_list, o);
}
@ -139,7 +122,7 @@ coap_get_obs_subject_by_token(const uint8_t *token, size_t token_len)
for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs;
obs = obs->next) {
PRINTF("Looking for token 0x%02X%02X\n", token[0], token[1]);
LOG_DBG("Looking for token 0x%02X%02X\n", token[0], token[1]);
if(obs->token_len == token_len
&& memcmp(obs->token, token, token_len) == 0) {
return obs;
@ -150,7 +133,7 @@ coap_get_obs_subject_by_token(const uint8_t *token, size_t token_len)
}
/*----------------------------------------------------------------------------*/
int
coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port,
coap_obs_remove_observee_by_token(const coap_endpoint_t *endpoint,
uint8_t *token, size_t token_len)
{
int removed = 0;
@ -158,9 +141,8 @@ coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port,
for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs;
obs = obs->next) {
PRINTF("Remove check Token 0x%02X%02X\n", token[0], token[1]);
if(uip_ipaddr_cmp(&obs->addr, addr)
&& obs->port == port
LOG_DBG("Remove check Token 0x%02X%02X\n", token[0], token[1]);
if(coap_endpoint_cmp(&obs->endpoint, endpoint)
&& obs->token_len == token_len
&& memcmp(obs->token, token, token_len) == 0) {
coap_obs_remove_observee(obs);
@ -171,7 +153,7 @@ coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port,
}
/*----------------------------------------------------------------------------*/
int
coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port,
coap_obs_remove_observee_by_url(const coap_endpoint_t *endpoint,
const char *url)
{
int removed = 0;
@ -179,9 +161,8 @@ coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port,
for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs;
obs = obs->next) {
PRINTF("Remove check URL %s\n", url);
if(uip_ipaddr_cmp(&obs->addr, addr)
&& obs->port == port
LOG_DBG("Remove check URL %s\n", url);
if(coap_endpoint_cmp(&obs->endpoint, endpoint)
&& (obs->url == url || memcmp(obs->url, url, strlen(obs->url)) == 0)) {
coap_obs_remove_observee(obs);
removed++;
@ -191,34 +172,31 @@ coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port,
}
/*----------------------------------------------------------------------------*/
static void
simple_reply(coap_message_type_t type, uip_ip6addr_t *addr, uint16_t port,
coap_packet_t *notification)
simple_reply(coap_message_type_t type, const coap_endpoint_t *endpoint,
coap_message_t *notification)
{
static coap_packet_t response[1];
static coap_message_t response[1];
size_t len;
coap_init_message(response, type, NO_ERROR, notification->mid);
len = coap_serialize_message(response, uip_appdata);
coap_send_message(addr, port, uip_appdata, len);
len = coap_serialize_message(response, coap_databuf());
coap_sendto(endpoint, coap_databuf(), len);
}
/*----------------------------------------------------------------------------*/
static coap_notification_flag_t
classify_notification(void *response, int first)
classify_notification(coap_message_t *response, int first)
{
coap_packet_t *pkt;
pkt = (coap_packet_t *)response;
if(!pkt) {
PRINTF("no response\n");
if(!response) {
LOG_DBG("no response\n");
return NO_REPLY_FROM_SERVER;
}
PRINTF("server replied\n");
if(!IS_RESPONSE_CODE_2_XX(pkt)) {
PRINTF("error response code\n");
LOG_DBG("server replied\n");
if(!IS_RESPONSE_CODE_2_XX(response)) {
LOG_DBG("error response code\n");
return ERROR_RESPONSE_CODE;
}
if(!IS_OPTION(pkt, COAP_OPTION_OBSERVE)) {
PRINTF("server does not support observe\n");
if(!coap_is_option(response, COAP_OPTION_OBSERVE)) {
LOG_DBG("server does not support observe\n");
return OBSERVE_NOT_SUPPORTED;
}
if(first) {
@ -228,35 +206,33 @@ classify_notification(void *response, int first)
}
/*----------------------------------------------------------------------------*/
void
coap_handle_notification(uip_ipaddr_t *addr, uint16_t port,
coap_packet_t *notification)
coap_handle_notification(const coap_endpoint_t *endpoint,
coap_message_t *notification)
{
coap_packet_t *pkt;
const uint8_t *token;
int token_len;
coap_observee_t *obs;
coap_notification_flag_t flag;
uint32_t observe;
PRINTF("coap_handle_notification()\n");
pkt = (coap_packet_t *)notification;
token_len = get_token(pkt, &token);
PRINTF("Getting token\n");
LOG_DBG("coap_handle_notification()\n");
token_len = get_token(notification, &token);
LOG_DBG("Getting token\n");
if(0 == token_len) {
PRINTF("Error while handling coap observe notification: "
"no token in message\n");
LOG_DBG("Error while handling coap observe notification: "
"no token in message\n");
return;
}
PRINTF("Getting observee info\n");
LOG_DBG("Getting observee info\n");
obs = coap_get_obs_subject_by_token(token, token_len);
if(NULL == obs) {
PRINTF("Error while handling coap observe notification: "
"no matching token found\n");
simple_reply(COAP_TYPE_RST, addr, port, notification);
LOG_DBG("Error while handling coap observe notification: "
"no matching token found\n");
simple_reply(COAP_TYPE_RST, endpoint, notification);
return;
}
if(notification->type == COAP_TYPE_CON) {
simple_reply(COAP_TYPE_ACK, addr, port, notification);
simple_reply(COAP_TYPE_ACK, endpoint, notification);
}
if(obs->notification_callback != NULL) {
flag = classify_notification(notification, 0);
@ -265,7 +241,7 @@ coap_handle_notification(uip_ipaddr_t *addr, uint16_t port,
if(flag == NOTIFICATION_OK) {
coap_get_header_observe(notification, &observe);
if(observe == obs->last_observe) {
PRINTF("Discarding duplicate\n");
LOG_DBG("Discarding duplicate\n");
return;
}
obs->last_observe = observe;
@ -275,13 +251,13 @@ coap_handle_notification(uip_ipaddr_t *addr, uint16_t port,
}
/*----------------------------------------------------------------------------*/
static void
handle_obs_registration_response(void *data, void *response)
handle_obs_registration_response(void *data, coap_message_t *response)
{
coap_observee_t *obs;
notification_callback_t notification_callback;
coap_notification_flag_t flag;
PRINTF("handle_obs_registration_response(): ");
LOG_DBG("handle_obs_registration_response()\n");
obs = (coap_observee_t *)data;
notification_callback = obs->notification_callback;
flag = classify_notification(response, 1);
@ -305,11 +281,11 @@ coap_generate_token(uint8_t **token_ptr)
}
/*----------------------------------------------------------------------------*/
coap_observee_t *
coap_obs_request_registration(uip_ipaddr_t *addr, uint16_t port, char *uri,
coap_obs_request_registration(const coap_endpoint_t *endpoint, char *uri,
notification_callback_t notification_callback,
void *data)
{
coap_packet_t request[1];
coap_message_t request[1];
coap_transaction_t *t;
uint8_t *token;
uint8_t token_len;
@ -321,22 +297,23 @@ coap_obs_request_registration(uip_ipaddr_t *addr, uint16_t port, char *uri,
coap_set_header_observe(request, 0);
token_len = coap_generate_token(&token);
set_token(request, token, token_len);
t = coap_new_transaction(request->mid, addr, port);
t = coap_new_transaction(request->mid, endpoint);
if(t) {
obs = coap_obs_add_observee(addr, port, (uint8_t *)token, token_len, uri,
obs = coap_obs_add_observee(endpoint, (uint8_t *)token, token_len, uri,
notification_callback, data);
if(obs) {
t->callback = handle_obs_registration_response;
t->callback_data = obs;
t->packet_len = coap_serialize_message(request, t->packet);
t->message_len = coap_serialize_message(request, t->message);
coap_send_transaction(t);
} else {
PRINTF("Could not allocate obs_subject resource buffer");
LOG_DBG("Could not allocate obs_subject resource buffer\n");
coap_clear_transaction(t);
}
} else {
PRINTF("Could not allocate transaction buffer");
LOG_DBG("Could not allocate transaction buffer\n");
}
return obs;
}
#endif /* COAP_OBSERVE_CLIENT */
/** @} */

View File

@ -37,6 +37,11 @@
* Daniele Alessandrelli <daniele.alessandrelli@gmail.com>
*/
/**
* \addtogroup coap
* @{
*/
#ifndef COAP_OBSERVING_CLIENT_H_
#define COAP_OBSERVING_CLIENT_H_
@ -79,8 +84,7 @@ typedef void (*notification_callback_t)(coap_observee_t *subject,
struct coap_observee_s {
coap_observee_t *next; /* for LIST */
uip_ipaddr_t addr;
uint16_t port;
coap_endpoint_t endpoint;
const char *url;
uint8_t token_len;
uint8_t token[COAP_TOKEN_LEN];
@ -90,7 +94,7 @@ struct coap_observee_s {
};
/*----------------------------------------------------------------------------*/
coap_observee_t *coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port,
coap_observee_t *coap_obs_add_observee(const coap_endpoint_t *endpoint,
const uint8_t *token, size_t token_len,
const char *url,
notification_callback_t
@ -101,17 +105,17 @@ void coap_obs_remove_observee(coap_observee_t *o);
coap_observee_t *coap_obs_get_observee_by_token(const uint8_t *token,
size_t token_len);
int coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port,
int coap_obs_remove_observee_by_token(const coap_endpoint_t *endpoint,
uint8_t *token, size_t token_len);
int coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port,
int coap_obs_remove_observee_by_url(const coap_endpoint_t *endpoint,
const char *url);
void coap_handle_notification(uip_ipaddr_t *addr, uint16_t port,
coap_packet_t *notification);
void coap_handle_notification(const coap_endpoint_t *endpoint,
coap_message_t *notification);
coap_observee_t *coap_obs_request_registration(uip_ipaddr_t *addr,
uint16_t port, char *uri,
coap_observee_t *coap_obs_request_registration(const coap_endpoint_t *endpoint,
char *uri,
notification_callback_t
notification_callback,
void *data);
@ -119,3 +123,4 @@ coap_observee_t *coap_obs_request_registration(uip_ipaddr_t *addr,
uint8_t coap_generate_token(uint8_t **token_ptr);
#endif /* COAP_OBSERVING_CLIENT_H_ */
/** @} */

View File

@ -36,21 +36,22 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
/**
* \addtogroup coap
* @{
*/
#include <stdio.h>
#include <string.h>
#include "coap-observe.h"
#include "coap-engine.h"
#include "lib/memb.h"
#include "lib/list.h"
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#define PRINTLLADDR(addr)
#endif
/* Log configuration */
#include "coap-log.h"
#define LOG_MODULE "coap-observe"
#define LOG_LEVEL LOG_LEVEL_COAP
/*---------------------------------------------------------------------------*/
MEMB(observers_memb, coap_observer_t, COAP_MAX_OBSERVERS);
@ -59,11 +60,11 @@ LIST(observers_list);
/*- Internal API ------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static coap_observer_t *
add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token,
add_observer(const coap_endpoint_t *endpoint, const uint8_t *token,
size_t token_len, const char *uri, int uri_len)
{
/* Remove existing observe relationship, if any. */
coap_remove_observer_by_uri(addr, port, uri);
coap_remove_observer_by_uri(endpoint, uri);
coap_observer_t *o = memb_alloc(&observers_memb);
@ -74,15 +75,14 @@ add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token,
}
memcpy(o->url, uri, max);
o->url[max] = 0;
uip_ipaddr_copy(&o->addr, addr);
o->port = port;
coap_endpoint_copy(&o->endpoint, endpoint);
o->token_len = token_len;
memcpy(o->token, token, token_len);
o->last_mid = 0;
PRINTF("Adding observer (%u/%u) for /%s [0x%02X%02X]\n",
list_length(observers_list) + 1, COAP_MAX_OBSERVERS,
o->url, o->token[0], o->token[1]);
LOG_INFO("Adding observer (%u/%u) for /%s [0x%02X%02X]\n",
list_length(observers_list) + 1, COAP_MAX_OBSERVERS,
o->url, o->token[0], o->token[1]);
list_add(observers_list, o);
}
@ -94,25 +94,25 @@ add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token,
void
coap_remove_observer(coap_observer_t *o)
{
PRINTF("Removing observer for /%s [0x%02X%02X]\n", o->url, o->token[0],
o->token[1]);
LOG_INFO("Removing observer for /%s [0x%02X%02X]\n", o->url, o->token[0],
o->token[1]);
memb_free(&observers_memb, o);
list_remove(observers_list, o);
}
/*---------------------------------------------------------------------------*/
int
coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port)
coap_remove_observer_by_client(const coap_endpoint_t *endpoint)
{
int removed = 0;
coap_observer_t *obs = NULL;
LOG_DBG("Remove check client ");
LOG_DBG_COAP_EP(endpoint);
LOG_DBG_("\n");
for(obs = (coap_observer_t *)list_head(observers_list); obs;
obs = obs->next) {
PRINTF("Remove check client ");
PRINT6ADDR(addr);
PRINTF(":%u\n", port);
if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port) {
if(coap_endpoint_cmp(&obs->endpoint, endpoint)) {
coap_remove_observer(obs);
removed++;
}
@ -121,7 +121,7 @@ coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port)
}
/*---------------------------------------------------------------------------*/
int
coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port,
coap_remove_observer_by_token(const coap_endpoint_t *endpoint,
uint8_t *token, size_t token_len)
{
int removed = 0;
@ -129,8 +129,8 @@ coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port,
for(obs = (coap_observer_t *)list_head(observers_list); obs;
obs = obs->next) {
PRINTF("Remove check Token 0x%02X%02X\n", token[0], token[1]);
if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port
LOG_DBG("Remove check Token 0x%02X%02X\n", token[0], token[1]);
if(coap_endpoint_cmp(&obs->endpoint, endpoint)
&& obs->token_len == token_len
&& memcmp(obs->token, token, token_len) == 0) {
coap_remove_observer(obs);
@ -141,7 +141,7 @@ coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port,
}
/*---------------------------------------------------------------------------*/
int
coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port,
coap_remove_observer_by_uri(const coap_endpoint_t *endpoint,
const char *uri)
{
int removed = 0;
@ -149,9 +149,9 @@ coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port,
for(obs = (coap_observer_t *)list_head(observers_list); obs;
obs = obs->next) {
PRINTF("Remove check URL %p\n", uri);
if((addr == NULL
|| (uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port))
LOG_DBG("Remove check URL %p\n", uri);
if((endpoint == NULL
|| (coap_endpoint_cmp(&obs->endpoint, endpoint)))
&& (obs->url == uri || memcmp(obs->url, uri, strlen(obs->url)) == 0)) {
coap_remove_observer(obs);
removed++;
@ -161,15 +161,15 @@ coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port,
}
/*---------------------------------------------------------------------------*/
int
coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid)
coap_remove_observer_by_mid(const coap_endpoint_t *endpoint, uint16_t mid)
{
int removed = 0;
coap_observer_t *obs = NULL;
for(obs = (coap_observer_t *)list_head(observers_list); obs;
obs = obs->next) {
PRINTF("Remove check MID %u\n", mid);
if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port
LOG_DBG("Remove check MID %u\n", mid);
if(coap_endpoint_cmp(&obs->endpoint, endpoint)
&& obs->last_mid == mid) {
coap_remove_observer(obs);
removed++;
@ -181,29 +181,40 @@ coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid)
/*- Notification ------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void
coap_notify_observers(resource_t *resource)
coap_notify_observers(coap_resource_t *resource)
{
coap_notify_observers_sub(resource, NULL);
}
/* Can be used either for sub - or when there is not resource - just
a handler */
void
coap_notify_observers_sub(resource_t *resource, const char *subpath)
coap_notify_observers_sub(coap_resource_t *resource, const char *subpath)
{
/* build notification */
coap_packet_t notification[1]; /* this way the packet can be treated as pointer as usual */
coap_packet_t request[1]; /* this way the packet can be treated as pointer as usual */
coap_message_t notification[1]; /* this way the message can be treated as pointer as usual */
coap_message_t request[1]; /* this way the message can be treated as pointer as usual */
coap_observer_t *obs = NULL;
int url_len, obs_url_len;
char url[COAP_OBSERVER_URL_LEN];
uint8_t sub_ok = 0;
url_len = strlen(resource->url);
strncpy(url, resource->url, COAP_OBSERVER_URL_LEN - 1);
if(url_len < COAP_OBSERVER_URL_LEN - 1 && subpath != NULL) {
strncpy(&url[url_len], subpath, COAP_OBSERVER_URL_LEN - url_len - 1);
if(resource != NULL) {
url_len = strlen(resource->url);
strncpy(url, resource->url, COAP_OBSERVER_URL_LEN - 1);
if(url_len < COAP_OBSERVER_URL_LEN - 1 && subpath != NULL) {
strncpy(&url[url_len], subpath, COAP_OBSERVER_URL_LEN - url_len - 1);
}
} else if(subpath != NULL) {
strncpy(url, subpath, COAP_OBSERVER_URL_LEN - 1);
} else {
/* No resource, no subpath */
return;
}
/* Ensure url is null terminated because strncpy does not guarantee this */
url[COAP_OBSERVER_URL_LEN - 1] = '\0';
/* url now contains the notify URL that needs to match the observer */
PRINTF("Observe: Notification from %s\n", url);
LOG_INFO("Notification from %s\n", url);
coap_init_message(notification, COAP_TYPE_NON, CONTENT_2_05, 0);
/* create a "fake" request for the URI */
@ -212,30 +223,35 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath)
/* iterate over observers */
url_len = strlen(url);
/* Assumes lazy evaluation... */
sub_ok = (resource == NULL) || (resource->flags & HAS_SUB_RESOURCES);
for(obs = (coap_observer_t *)list_head(observers_list); obs;
obs = obs->next) {
obs_url_len = strlen(obs->url);
/* Do a match based on the parent/sub-resource match so that it is
possible to do parent-node observe */
/***** TODO fix here so that we handle the notofication correctly ******/
/* All the new-style ... is assuming that the URL might be within */
if((obs_url_len == url_len
|| (obs_url_len > url_len
&& (resource->flags & HAS_SUB_RESOURCES)
&& sub_ok
&& obs->url[url_len] == '/'))
&& strncmp(url, obs->url, url_len) == 0) {
coap_transaction_t *transaction = NULL;
/*TODO implement special transaction for CON, sharing the same buffer to allow for more observers */
if((transaction = coap_new_transaction(coap_get_mid(), &obs->addr, obs->port))) {
if((transaction = coap_new_transaction(coap_get_mid(), &obs->endpoint))) {
if(obs->obs_counter % COAP_OBSERVE_REFRESH_INTERVAL == 0) {
PRINTF(" Force Confirmable for\n");
LOG_DBG(" Force Confirmable for\n");
notification->type = COAP_TYPE_CON;
}
PRINTF(" Observer ");
PRINT6ADDR(&obs->addr);
PRINTF(":%u\n", obs->port);
LOG_DBG(" Observer ");
LOG_DBG_COAP_EP(&obs->endpoint);
LOG_DBG_("\n");
/* update last MID for RST matching */
obs->last_mid = transaction->mid;
@ -243,9 +259,21 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath)
/* prepare response */
notification->mid = transaction->mid;
resource->get_handler(request, notification,
transaction->packet + COAP_MAX_HEADER_SIZE,
REST_MAX_CHUNK_SIZE, NULL);
/* Either old style get_handler or the full handler */
if(coap_call_handlers(request, notification, transaction->message +
COAP_MAX_HEADER_SIZE, COAP_MAX_CHUNK_SIZE,
NULL) > 0) {
LOG_DBG("Notification on new handlers\n");
} else {
if(resource != NULL) {
resource->get_handler(request, notification,
transaction->message + COAP_MAX_HEADER_SIZE,
COAP_MAX_CHUNK_SIZE, NULL);
} else {
/* What to do here? */
notification->code = BAD_REQUEST_4_00;
}
}
if(notification->code < BAD_REQUEST_4_00) {
coap_set_header_observe(notification, (obs->obs_counter)++);
@ -254,8 +282,8 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath)
}
coap_set_token(notification, obs->token, obs->token_len);
transaction->packet_len =
coap_serialize_message(notification, transaction->packet);
transaction->message_len =
coap_serialize_message(notification, transaction->message);
coap_send_transaction(transaction);
}
@ -264,16 +292,21 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath)
}
/*---------------------------------------------------------------------------*/
void
coap_observe_handler(resource_t *resource, void *request, void *response)
coap_observe_handler(coap_resource_t *resource, coap_message_t *coap_req,
coap_message_t *coap_res)
{
coap_packet_t *const coap_req = (coap_packet_t *)request;
coap_packet_t *const coap_res = (coap_packet_t *)response;
const coap_endpoint_t *src_ep;
coap_observer_t *obs;
LOG_DBG("CoAP observer handler rsc: %d\n", resource != NULL);
if(coap_req->code == COAP_GET && coap_res->code < 128) { /* GET request and response without error code */
if(IS_OPTION(coap_req, COAP_OPTION_OBSERVE)) {
if(coap_req->observe == 0) {
obs = add_observer(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport,
if(coap_is_option(coap_req, COAP_OPTION_OBSERVE)) {
src_ep = coap_get_src_endpoint(coap_req);
if(src_ep == NULL) {
/* No source endpoint, can not add */
} else if(coap_req->observe == 0) {
obs = add_observer(src_ep,
coap_req->token, coap_req->token_len,
coap_req->uri_path, coap_req->uri_path_len);
if(obs) {
@ -300,11 +333,11 @@ coap_observe_handler(resource_t *resource, void *request, void *response)
} else if(coap_req->observe == 1) {
/* remove client if it is currently observe */
coap_remove_observer_by_token(&UIP_IP_BUF->srcipaddr,
UIP_UDP_BUF->srcport, coap_req->token,
coap_req->token_len);
coap_remove_observer_by_token(src_ep,
coap_req->token, coap_req->token_len);
}
}
}
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -36,53 +36,49 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
/**
* \addtogroup coap
* @{
*/
#ifndef COAP_OBSERVE_H_
#define COAP_OBSERVE_H_
#include "coap.h"
#include "coap-transactions.h"
#include "stimer.h"
#include "coap-engine.h"
#define COAP_OBSERVER_URL_LEN 20
typedef struct coap_observable {
uint32_t observe_clock;
struct stimer orphan_timer;
list_t observers;
coap_packet_t notification;
uint8_t buffer[COAP_MAX_PACKET_SIZE + 1];
} coap_observable_t;
typedef struct coap_observer {
struct coap_observer *next; /* for LIST */
char url[COAP_OBSERVER_URL_LEN];
uip_ipaddr_t addr;
uint16_t port;
coap_endpoint_t endpoint;
uint8_t token_len;
uint8_t token[COAP_TOKEN_LEN];
uint16_t last_mid;
int32_t obs_counter;
struct etimer retrans_timer;
coap_timer_t retrans_timer;
uint8_t retrans_counter;
} coap_observer_t;
list_t coap_get_observers(void);
void coap_remove_observer(coap_observer_t *o);
int coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port);
int coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port,
int coap_remove_observer_by_client(const coap_endpoint_t *ep);
int coap_remove_observer_by_token(const coap_endpoint_t *ep,
uint8_t *token, size_t token_len);
int coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port,
int coap_remove_observer_by_uri(const coap_endpoint_t *ep,
const char *uri);
int coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port,
int coap_remove_observer_by_mid(const coap_endpoint_t *ep,
uint16_t mid);
void coap_notify_observers(resource_t *resource);
void coap_notify_observers_sub(resource_t *resource, const char *subpath);
void coap_notify_observers(coap_resource_t *resource);
void coap_notify_observers_sub(coap_resource_t *resource, const char *subpath);
void coap_observe_handler(resource_t *resource, void *request,
void *response);
void coap_observe_handler(coap_resource_t *resource, coap_message_t *request,
coap_message_t *response);
#endif /* COAP_OBSERVE_H_ */
/** @} */

View File

@ -36,20 +36,19 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include <string.h>
#include "coap-engine.h"
/**
* \addtogroup coap
* @{
*/
#define DEBUG 0
#if DEBUG
#include "coap-engine.h"
#include <string.h>
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#define PRINTLLADDR(addr)
#endif
/* Log configuration */
#include "coap-log.h"
#define LOG_MODULE "coap-res-well-known-core"
#define LOG_LEVEL LOG_LEVEL_COAP
#define ADD_CHAR_IF_POSSIBLE(char) \
if(strpos >= *offset && bufpos < preferred_size) { \
@ -67,7 +66,7 @@
+ (*offset - (int32_t)strpos > 0 ? \
*offset - (int32_t)strpos : 0)); \
if(bufpos op preferred_size) { \
PRINTF("res: BREAK at %s (%p)\n", string, resource); \
LOG_DBG("BREAK at %s (%p)\n", string, resource); \
break; \
} \
} \
@ -76,14 +75,15 @@
/*---------------------------------------------------------------------------*/
/*- Resource Handlers -------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void
well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
static void
well_known_core_get_handler(coap_message_t *request, coap_message_t *response,
uint8_t *buffer, uint16_t preferred_size,
int32_t *offset)
{
size_t strpos = 0; /* position in overall string (which is larger than the buffer) */
size_t bufpos = 0; /* position within buffer (bytes written) */
size_t tmplen = 0;
resource_t *resource = NULL;
coap_resource_t *resource = NULL;
#if COAP_LINK_FORMAT_FILTERING
/* For filtering. */
@ -101,7 +101,9 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
++value;
len -= strlen(filter) + 1;
PRINTF("Filter %s = %.*s\n", filter, len, value);
LOG_DBG("Filter %s = ", filter);
LOG_DBG_COAP_STRING(value, len);
LOG_DBG_("\n");
if(strcmp(filter, "href") == 0 && value[0] == '/') {
++value;
@ -111,10 +113,10 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
lastchar = value[len - 1];
value[len - 1] = '\0';
}
#endif
#endif /* COAP_LINK_FORMAT_FILTERING */
for(resource = (resource_t *)list_head(rest_get_resources()); resource;
resource = resource->next) {
for(resource = coap_get_first_resource(); resource;
resource = coap_get_next_resource(resource)) {
#if COAP_LINK_FORMAT_FILTERING
/* Filtering */
if(len) {
@ -135,7 +137,7 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
end = strchr(attrib, '"');
}
PRINTF("Filter: res has attrib %s (%s)\n", attrib, value);
LOG_DBG("Filter: res has attrib %s (%s)\n", attrib, value);
found = attrib;
while((found = strstr(found, value)) != NULL) {
if(found > end) {
@ -150,17 +152,17 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
if(found == NULL) {
continue;
}
PRINTF("Filter: res has prefix %s\n", found);
LOG_DBG("Filter: res has prefix %s\n", found);
if(lastchar != '*'
&& (found[len] != '"' && found[len] != ' ' && found[len] != '\0')) {
continue;
}
PRINTF("Filter: res has match\n");
LOG_DBG("Filter: res has match\n");
}
#endif
PRINTF("res: /%s (%p)\npos: s%zu, o%ld, b%zu\n", resource->url, resource,
strpos, (long)*offset, bufpos);
LOG_DBG("/%s (%p)\npos: s%zu, o%ld, b%zu\n", resource->url, resource,
strpos, (long)*offset, bufpos);
if(strpos > 0) {
ADD_CHAR_IF_POSSIBLE(',');
@ -177,28 +179,30 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
/* buffer full, but resource not completed yet; or: do not break if resource exactly fills buffer. */
if(bufpos > preferred_size && strpos - bufpos > *offset) {
PRINTF("res: BREAK at %s (%p)\n", resource->url, resource);
LOG_DBG("BREAK at %s (%p)\n", resource->url, resource);
break;
}
}
if(bufpos > 0) {
PRINTF("BUF %zu: %.*s\n", bufpos, (int)bufpos, (char *)buffer);
LOG_DBG("BUF %zu: ", bufpos);
LOG_DBG_COAP_STRING((char *)buffer, bufpos);
LOG_DBG_("\n");
coap_set_payload(response, buffer, bufpos);
coap_set_header_content_format(response, APPLICATION_LINK_FORMAT);
} else if(strpos > 0) {
PRINTF("well_known_core_handler(): bufpos<=0\n");
LOG_DBG("well_known_core_handler(): bufpos<=0\n");
coap_set_status_code(response, BAD_OPTION_4_02);
coap_set_payload(response, "BlockOutOfScope", 15);
}
if(resource == NULL) {
PRINTF("res: DONE\n");
LOG_DBG("DONE\n");
*offset = -1;
} else {
PRINTF("res: MORE at %s (%p)\n", resource->url, resource);
LOG_DBG("MORE at %s (%p)\n", resource->url, resource);
*offset += preferred_size;
}
}
@ -206,3 +210,4 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
RESOURCE(res_well_known_core, "ct=40", well_known_core_get_handler, NULL,
NULL, NULL);
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -36,23 +36,21 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include "sys/cc.h"
#include <stdio.h>
#include <string.h>
/**
* \addtogroup coap
* @{
*/
#include "coap.h"
#include "coap-separate.h"
#include "coap-transactions.h"
#include "sys/cc.h"
#include <string.h>
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#define PRINTLLADDR(addr)
#endif
/* Log configuration */
#include "coap-log.h"
#define LOG_MODULE "coap-separate"
#define LOG_LEVEL LOG_LEVEL_COAP
/*---------------------------------------------------------------------------*/
/*- Separate Response API ---------------------------------------------------*/
@ -69,13 +67,13 @@ void
coap_separate_reject()
{
/* TODO: Accept string pointer for custom error message */
erbium_status_code = SERVICE_UNAVAILABLE_5_03;
coap_status_code = SERVICE_UNAVAILABLE_5_03;
coap_error_message = "AlreadyInUse";
}
/*----------------------------------------------------------------------------*/
/**
* \brief Initiate a separate response with an empty ACK
* \param request The request to accept
* \param coap_req The request to accept
* \param separate_store A pointer to the data structure that will store the
* relevant information for the response
*
@ -85,29 +83,33 @@ coap_separate_reject()
* then retry later.
*/
void
coap_separate_accept(void *request, coap_separate_t *separate_store)
coap_separate_accept(coap_message_t *coap_req, coap_separate_t *separate_store)
{
coap_packet_t *const coap_req = (coap_packet_t *)request;
coap_transaction_t *const t = coap_get_transaction_by_mid(coap_req->mid);
PRINTF("Separate ACCEPT: /%.*s MID %u\n", coap_req->uri_path_len,
coap_req->uri_path, coap_req->mid);
LOG_DBG("Separate ACCEPT: /");
LOG_DBG_COAP_STRING(coap_req->uri_path, coap_req->uri_path_len);
LOG_DBG_(" MID %u\n", coap_req->mid);
if(t) {
/* send separate ACK for CON */
if(coap_req->type == COAP_TYPE_CON) {
coap_packet_t ack[1];
coap_message_t ack[1];
const coap_endpoint_t *ep;
/* ACK with empty code (0) */
coap_init_message(ack, COAP_TYPE_ACK, 0, coap_req->mid);
/* serializing into IPBUF: Only overwrites header parts that are already parsed into the request struct */
coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport,
(uip_appdata), coap_serialize_message(ack,
uip_appdata));
ep = coap_get_src_endpoint(coap_req);
if(ep == NULL) {
LOG_ERR("ERROR: no endpoint in request\n");
} else {
/* ACK with empty code (0) */
coap_init_message(ack, COAP_TYPE_ACK, 0, coap_req->mid);
/* serializing into IPBUF: Only overwrites header parts that are already parsed into the request struct */
coap_sendto(ep, coap_databuf(),
coap_serialize_message(ack, coap_databuf()));
}
}
/* store remote address */
uip_ipaddr_copy(&separate_store->addr, &t->addr);
separate_store->port = t->port;
/* store remote endpoint address */
coap_endpoint_copy(&separate_store->endpoint, &t->endpoint);
/* store correct response type */
separate_store->type =
@ -124,15 +126,15 @@ coap_separate_accept(void *request, coap_separate_t *separate_store)
separate_store->block2_size = coap_req->block2_size > 0 ? MIN(COAP_MAX_BLOCK_SIZE, coap_req->block2_size) : COAP_MAX_BLOCK_SIZE;
/* signal the engine to skip automatic response and clear transaction by engine */
erbium_status_code = MANUAL_RESPONSE;
coap_status_code = MANUAL_RESPONSE;
} else {
PRINTF("ERROR: Response transaction for separate request not found!\n");
erbium_status_code = INTERNAL_SERVER_ERROR_5_00;
LOG_ERR("ERROR: Response transaction for separate request not found!\n");
coap_status_code = INTERNAL_SERVER_ERROR_5_00;
}
}
/*----------------------------------------------------------------------------*/
void
coap_separate_resume(void *response, coap_separate_t *separate_store,
coap_separate_resume(coap_message_t *response, coap_separate_t *separate_store,
uint8_t code)
{
coap_init_message(response, separate_store->type, code,
@ -147,3 +149,4 @@ coap_separate_resume(void *response, coap_separate_t *separate_store,
}
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -36,15 +36,20 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
/**
* \addtogroup coap
* @{
*/
#ifndef COAP_SEPARATE_H_
#define COAP_SEPARATE_H_
#include "coap.h"
#include "coap-engine.h"
typedef struct coap_separate {
uip_ipaddr_t addr;
uint16_t port;
coap_endpoint_t endpoint;
coap_message_type_t type;
uint16_t mid;
@ -59,11 +64,14 @@ typedef struct coap_separate {
uint16_t block2_size;
} coap_separate_t;
int coap_separate_handler(resource_t *resource, void *request,
void *response);
int coap_separate_handler(coap_resource_t *resource, coap_message_t *request,
coap_message_t *response);
void coap_separate_reject(void);
void coap_separate_accept(void *request, coap_separate_t *separate_store);
void coap_separate_resume(void *response, coap_separate_t *separate_store,
void coap_separate_accept(coap_message_t *request,
coap_separate_t *separate_store);
void coap_separate_resume(coap_message_t *response,
coap_separate_t *separate_store,
uint8_t code);
#endif /* COAP_SEPARATE_H_ */
/** @} */

View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 2016, SICS, Swedish ICT AB.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/**
* \file
* CoAP timer driver implementation based on Contiki etimers
* \author
* Niclas Finne <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
/**
* \addtogroup coap-timer
* @{
*
* \defgroup coap-timer-default CoAP timer for Contiki-NG
* @{
*
* This is an implementation of CoAP timer for Contiki-NG.
*/
#include "coap-timer.h"
#include "sys/clock.h"
#include "sys/etimer.h"
#include "sys/process.h"
/* Log configuration */
#include "coap-log.h"
#define LOG_MODULE "coap-timer-default"
#define LOG_LEVEL LOG_LEVEL_NONE
PROCESS(coap_timer_process, "coap timer process");
static uint64_t current_time;
static struct etimer timer;
/*---------------------------------------------------------------------------*/
static void
update_timer(void)
{
uint64_t remaining;
remaining = coap_timer_time_to_next_expiration();
LOG_DBG("remaining %lu msec\n", (unsigned long)remaining);
if(remaining == 0) {
/* Run as soon as possible */
process_poll(&coap_timer_process);
} else {
remaining *= CLOCK_SECOND;
remaining /= 1000;
if(remaining > CLOCK_SECOND * 60) {
/* Make sure the CoAP timer clock is updated at least once per minute */
remaining = CLOCK_SECOND * 60;
} else if(remaining < 1) {
/* Wait minimum one system clock tick */
remaining = 1;
}
etimer_set(&timer, (clock_time_t)remaining);
}
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(coap_timer_process, ev, data)
{
PROCESS_BEGIN();
etimer_set(&timer, CLOCK_SECOND);
while(1) {
PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER ||
ev == PROCESS_EVENT_POLL);
if(coap_timer_run()) {
/* Needs to run again */
process_poll(&coap_timer_process);
} else {
update_timer();
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
static uint64_t
uptime(void)
{
static clock_time_t last;
clock_time_t now;
uint64_t diff;
now = clock_time();
diff = (clock_time_t)(now - last);
if(diff > 0) {
current_time += (diff * 1000) / CLOCK_SECOND;
last = now;
}
return current_time;
}
/*---------------------------------------------------------------------------*/
static void
init(void)
{
process_start(&coap_timer_process, NULL);
}
/*---------------------------------------------------------------------------*/
static void
update(void)
{
process_poll(&coap_timer_process);
}
/*---------------------------------------------------------------------------*/
const coap_timer_driver_t coap_timer_default_driver = {
.init = init,
.uptime = uptime,
.update = update,
};
/*---------------------------------------------------------------------------*/
/** @} */
/** @} */

View File

@ -0,0 +1,188 @@
/*
* Copyright (c) 2016, SICS, Swedish ICT AB.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/**
* \file
* CoAP timer implementation.
* \author
* Niclas Finne <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
/**
* \addtogroup coap-timer
* @{
*/
#include "coap-timer.h"
#include "lib/list.h"
#include "sys/cc.h"
/* Log configuration */
#include "coap-log.h"
#define LOG_MODULE "coap-timer"
#define LOG_LEVEL LOG_LEVEL_NONE
LIST(timer_list);
static uint8_t is_initialized;
/*---------------------------------------------------------------------------*/
static void
add_timer(coap_timer_t *timer)
{
coap_timer_t *n, *l, *p;
if(!is_initialized) {
/* The coap_timer system has not yet been initialized */
coap_timer_init();
}
LOG_DBG("adding timer %p at %lu\n", timer,
(unsigned long)timer->expiration_time);
p = list_head(timer_list);
/* Make sure the timer is not already added to the timer list */
list_remove(timer_list, timer);
for(l = NULL, n = list_head(timer_list); n != NULL; l = n, n = n->next) {
if(timer->expiration_time < n->expiration_time) {
list_insert(timer_list, l, timer);
timer = NULL;
break;
}
}
if(timer != NULL) {
list_insert(timer_list, l, timer);
}
if(p != list_head(timer_list)) {
/* The next timer to expire has changed so we need to notify the driver */
COAP_TIMER_DRIVER.update();
}
}
/*---------------------------------------------------------------------------*/
void
coap_timer_stop(coap_timer_t *timer)
{
LOG_DBG("stopping timer %p\n", timer);
/* Mark timer as expired right now */
timer->expiration_time = coap_timer_uptime();
list_remove(timer_list, timer);
}
/*---------------------------------------------------------------------------*/
void
coap_timer_set(coap_timer_t *timer, uint64_t time)
{
timer->expiration_time = coap_timer_uptime() + time;
add_timer(timer);
}
/*---------------------------------------------------------------------------*/
void
coap_timer_reset(coap_timer_t *timer, uint64_t time)
{
timer->expiration_time += time;
add_timer(timer);
}
/*---------------------------------------------------------------------------*/
uint64_t
coap_timer_time_to_next_expiration(void)
{
uint64_t now;
coap_timer_t *next;
next = list_head(timer_list);
if(next == NULL) {
/* No pending timers - return a time in the future */
return 60000;
}
now = coap_timer_uptime();
if(now < next->expiration_time) {
return next->expiration_time - now;
}
/* The next timer should already have expired */
return 0;
}
/*---------------------------------------------------------------------------*/
int
coap_timer_run(void)
{
uint64_t now;
coap_timer_t *next;
/* Always get the current time because it might trigger clock updates */
now = coap_timer_uptime();
next = list_head(timer_list);
if(next == NULL) {
/* No pending timers */
return 0;
}
if(next->expiration_time <= now) {
LOG_DBG("timer %p expired at %lu\n", next, (unsigned long)now);
/* This timer should expire now */
list_remove(timer_list, next);
if(next->callback) {
next->callback(next);
}
/* The next timer has changed */
COAP_TIMER_DRIVER.update();
/* Check if there is another pending timer */
next = list_head(timer_list);
if(next != NULL && next->expiration_time <= coap_timer_uptime()) {
/* Need to run again */
return 1;
}
}
return 0;
}
/*---------------------------------------------------------------------------*/
void
coap_timer_init(void)
{
if(is_initialized) {
return;
}
is_initialized = 1;
list_init(timer_list);
if(COAP_TIMER_DRIVER.init) {
COAP_TIMER_DRIVER.init();
}
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,210 @@
/*
* Copyright (c) 2016, SICS, Swedish ICT AB.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/**
* \file
* CoAP timer API.
* \author
* Niclas Finne <nfi@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
/**
* \addtogroup coap
* @{
*
* \defgroup coap-timer CoAP timer API
* @{
*
* The CoAP timer API defines a common interface for CoAP timer and time functionality.
*/
#ifndef COAP_TIMER_H_
#define COAP_TIMER_H_
#include "contiki.h"
#include <stdint.h>
typedef struct coap_timer coap_timer_t;
struct coap_timer {
coap_timer_t *next;
void (* callback)(coap_timer_t *);
void *user_data;
uint64_t expiration_time;
};
typedef struct {
void (* init)(void);
uint64_t (* uptime)(void);
void (* update)(void);
} coap_timer_driver_t;
#ifndef COAP_TIMER_DRIVER
#ifdef COAP_TIMER_CONF_DRIVER
#define COAP_TIMER_DRIVER COAP_TIMER_CONF_DRIVER
#else /* COAP_TIMER_CONF_DRIVER */
#define COAP_TIMER_DRIVER coap_timer_default_driver
#endif /* COAP_TIMER_CONF_DRIVER */
#endif /* COAP_TIMER_DRIVER */
extern const coap_timer_driver_t COAP_TIMER_DRIVER;
/**
* \brief Get the time since boot in milliseconds.
* \return The number of milliseconds since boot.
*/
static inline uint64_t
coap_timer_uptime(void)
{
return COAP_TIMER_DRIVER.uptime();
}
/**
* \brief Get the time since boot in seconds.
* \return The number of seconds since boot.
*/
static inline uint32_t
coap_timer_seconds(void)
{
return (uint32_t)(COAP_TIMER_DRIVER.uptime() / 1000);
}
/**
* \brief Set a callback function to be called when a CoAP timer expires.
*
* \param timer A pointer to a CoAP timer.
* \param callback A callback function.
*/
static inline void
coap_timer_set_callback(coap_timer_t *timer, void (* callback)(coap_timer_t *))
{
timer->callback = callback;
}
/**
* \brief Get user data that has been attached to a CoAP timer.
*
* \param timer A pointer to a CoAP timer.
* \return An opaque pointer to user data or NULL if no user data is
* attached to the timer.
*/
static inline void *
coap_timer_get_user_data(coap_timer_t *timer)
{
return timer->user_data;
}
/**
* \brief Attach user data to a CoAP timer.
*
* \param timer A pointer to a CoAP timer.
* \param data An opaque pointer to user data.
*/
static inline void
coap_timer_set_user_data(coap_timer_t *timer, void *data)
{
timer->user_data = data;
}
/**
* \brief Check if a CoAP timer has expired.
*
* \param timer A pointer to a CoAP timer.
* \return Non-zero if the timer has expired, zero otherwise.
*/
static inline int
coap_timer_expired(const coap_timer_t *timer)
{
return timer->expiration_time <= coap_timer_uptime();
}
/**
* \brief Stop a pending CoAP timer.
*
* After this function has been called, the timer will be expired
* and will not call the callback function.
*
* \param timer A pointer to a CoAP timer.
*/
void coap_timer_stop(coap_timer_t *timer);
/**
* \brief Set a CoAP timer to expire after the specified time.
*
* \param timer A pointer to a CoAP timer.
* \param time The time until the timer expires.
*/
void coap_timer_set(coap_timer_t *timer, uint64_t time);
/**
* \brief Reset a CoAP timer to expire a specified time after the
* last expiration time.
*
* This function sets the CoAP timer to expire the specified time
* after the previous expiration time. If the new expiration time
* has already passed, the timer will expire as soon as possible.
*
* If the timer has not yet expired when this function is called,
* the time until the timer expires will be extended by the
* specified time.
*
* \param timer A pointer to a CoAP timer.
* \param time The time after previous expiration the timer expires.
*/
void coap_timer_reset(coap_timer_t *timer, uint64_t time);
/**
* Get the time until next CoAP timer expires or 0 if there already exists
* expired timers that have not yet been processed. This function is normally
* never called by application code.
*
* Returns the time to next CoAP timer expires or 0 if unprocessed expired
* timers exists. Returns a time in the future if there are no timers pending.
*/
uint64_t coap_timer_time_to_next_expiration(void);
/**
* This function must be called periodically by the CoAP timer driver to
* process any expired CoAP timers. This function is normally never called by
* application code.
*
* Returns non-zero if it needs to run again to process more timers.
*/
int coap_timer_run(void);
/**
* This function initializes the CoAP timer library. It is automatically
* called at first use of a CoAP timer. This function is normally never called
* by application code.
*/
void coap_timer_init(void);
#endif /* COAP_TIMER_H_ */
/** @} */
/** @} */

View File

@ -36,39 +36,47 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include "contiki.h"
#include "contiki-net.h"
/**
* \addtogroup coap
* @{
*/
#include "coap-transactions.h"
#include "coap-observe.h"
#include "coap-timer.h"
#include "lib/memb.h"
#include "lib/list.h"
#include <stdlib.h>
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#define PRINTLLADDR(addr)
#endif
/* Log configuration */
#include "coap-log.h"
#define LOG_MODULE "coap-transactions"
#define LOG_LEVEL LOG_LEVEL_COAP
/*---------------------------------------------------------------------------*/
MEMB(transactions_memb, coap_transaction_t, COAP_MAX_OPEN_TRANSACTIONS);
LIST(transactions_list);
static struct process *transaction_handler_process = NULL;
/*---------------------------------------------------------------------------*/
static void
coap_retransmit_transaction(coap_timer_t *nt)
{
coap_transaction_t *t = coap_timer_get_user_data(nt);
if(t == NULL) {
LOG_DBG("No retransmission data in coap_timer!\n");
return;
}
++(t->retrans_counter);
LOG_DBG("Retransmitting %u (%u)\n", t->mid, t->retrans_counter);
coap_send_transaction(t);
}
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*- Internal API ------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void
coap_register_as_transaction_handler()
{
transaction_handler_process = PROCESS_CURRENT();
}
coap_transaction_t *
coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, uint16_t port)
coap_new_transaction(uint16_t mid, const coap_endpoint_t *endpoint)
{
coap_transaction_t *t = memb_alloc(&transactions_memb);
@ -77,8 +85,7 @@ coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, uint16_t port)
t->retrans_counter = 0;
/* save client address */
uip_ipaddr_copy(&t->addr, addr);
t->port = port;
coap_endpoint_copy(&t->endpoint, endpoint);
list_add(transactions_list, t); /* list itself makes sure same element is not added twice */
}
@ -89,43 +96,40 @@ coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, uint16_t port)
void
coap_send_transaction(coap_transaction_t *t)
{
PRINTF("Sending transaction %u\n", t->mid);
LOG_DBG("Sending transaction %u\n", t->mid);
coap_send_message(&t->addr, t->port, t->packet, t->packet_len);
coap_sendto(&t->endpoint, t->message, t->message_len);
if(COAP_TYPE_CON ==
((COAP_HEADER_TYPE_MASK & t->packet[0]) >> COAP_HEADER_TYPE_POSITION)) {
((COAP_HEADER_TYPE_MASK & t->message[0]) >> COAP_HEADER_TYPE_POSITION)) {
if(t->retrans_counter < COAP_MAX_RETRANSMIT) {
/* not timed out yet */
PRINTF("Keeping transaction %u\n", t->mid);
LOG_DBG("Keeping transaction %u\n", t->mid);
if(t->retrans_counter == 0) {
t->retrans_timer.timer.interval =
COAP_RESPONSE_TIMEOUT_TICKS + (random_rand()
%
(clock_time_t)
coap_timer_set_callback(&t->retrans_timer, coap_retransmit_transaction);
coap_timer_set_user_data(&t->retrans_timer, t);
t->retrans_interval =
COAP_RESPONSE_TIMEOUT_TICKS + (rand() %
COAP_RESPONSE_TIMEOUT_BACKOFF_MASK);
PRINTF("Initial interval %f\n",
(float)t->retrans_timer.timer.interval / CLOCK_SECOND);
LOG_DBG("Initial interval %lu msec\n",
(unsigned long)t->retrans_interval);
} else {
t->retrans_timer.timer.interval <<= 1; /* double */
PRINTF("Doubled (%u) interval %f\n", t->retrans_counter,
(float)t->retrans_timer.timer.interval / CLOCK_SECOND);
t->retrans_interval <<= 1; /* double */
LOG_DBG("Doubled (%u) interval %lu s\n", t->retrans_counter,
(unsigned long)(t->retrans_interval / 1000));
}
PROCESS_CONTEXT_BEGIN(transaction_handler_process);
etimer_restart(&t->retrans_timer); /* interval updated above */
PROCESS_CONTEXT_END(transaction_handler_process);
t = NULL;
/* interval updated above */
coap_timer_set(&t->retrans_timer, t->retrans_interval);
} else {
/* timed out */
PRINTF("Timeout\n");
restful_response_handler callback = t->callback;
LOG_DBG("Timeout\n");
coap_resource_response_handler_t callback = t->callback;
void *callback_data = t->callback_data;
/* handle observers */
coap_remove_observer_by_client(&t->addr, t->port);
coap_remove_observer_by_client(&t->endpoint);
coap_clear_transaction(t);
@ -142,13 +146,14 @@ void
coap_clear_transaction(coap_transaction_t *t)
{
if(t) {
PRINTF("Freeing transaction %u: %p\n", t->mid, t);
LOG_DBG("Freeing transaction %u: %p\n", t->mid, t);
etimer_stop(&t->retrans_timer);
coap_timer_stop(&t->retrans_timer);
list_remove(transactions_list, t);
memb_free(&transactions_memb, t);
}
}
/*---------------------------------------------------------------------------*/
coap_transaction_t *
coap_get_transaction_by_mid(uint16_t mid)
{
@ -156,24 +161,11 @@ coap_get_transaction_by_mid(uint16_t mid)
for(t = (coap_transaction_t *)list_head(transactions_list); t; t = t->next) {
if(t->mid == mid) {
PRINTF("Found transaction for MID %u: %p\n", t->mid, t);
LOG_DBG("Found transaction for MID %u: %p\n", t->mid, t);
return t;
}
}
return NULL;
}
/*---------------------------------------------------------------------------*/
void
coap_check_transactions()
{
coap_transaction_t *t = NULL;
for(t = (coap_transaction_t *)list_head(transactions_list); t; t = t->next) {
if(etimer_expired(&t->retrans_timer)) {
++(t->retrans_counter);
PRINTF("Retransmitting %u (%u)\n", t->mid, t->retrans_counter);
coap_send_transaction(t);
}
}
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -36,45 +36,48 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
/**
* \addtogroup coap
* @{
*/
#ifndef COAP_TRANSACTIONS_H_
#define COAP_TRANSACTIONS_H_
#include "coap.h"
#include "coap-engine.h"
#include "coap-timer.h"
/*
* Modulo mask (thus +1) for a random number to get the tick number for the random
* retransmission time between COAP_RESPONSE_TIMEOUT and COAP_RESPONSE_TIMEOUT*COAP_RESPONSE_RANDOM_FACTOR.
*/
#define COAP_RESPONSE_TIMEOUT_TICKS (CLOCK_SECOND * COAP_RESPONSE_TIMEOUT)
#define COAP_RESPONSE_TIMEOUT_BACKOFF_MASK (long)((CLOCK_SECOND * COAP_RESPONSE_TIMEOUT * ((float)COAP_RESPONSE_RANDOM_FACTOR - 1.0)) + 0.5) + 1
#define COAP_RESPONSE_TIMEOUT_TICKS (1000 * COAP_RESPONSE_TIMEOUT)
#define COAP_RESPONSE_TIMEOUT_BACKOFF_MASK (uint32_t)(((1000 * COAP_RESPONSE_TIMEOUT * ((float)COAP_RESPONSE_RANDOM_FACTOR - 1.0)) + 0.5) + 1)
/* container for transactions with message buffer and retransmission info */
typedef struct coap_transaction {
struct coap_transaction *next; /* for LIST */
uint16_t mid;
struct etimer retrans_timer;
coap_timer_t retrans_timer;
uint32_t retrans_interval;
uint8_t retrans_counter;
uip_ipaddr_t addr;
uint16_t port;
coap_endpoint_t endpoint;
restful_response_handler callback;
coap_resource_response_handler_t callback;
void *callback_data;
uint16_t packet_len;
uint8_t packet[COAP_MAX_PACKET_SIZE + 1]; /* +1 for the terminating '\0' which will not be sent
uint16_t message_len;
uint8_t message[COAP_MAX_PACKET_SIZE + 1]; /* +1 for the terminating '\0' which will not be sent
* Use snprintf(buf, len+1, "", ...) to completely fill payload */
} coap_transaction_t;
void coap_register_as_transaction_handler(void);
coap_transaction_t *coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr,
uint16_t port);
coap_transaction_t *coap_new_transaction(uint16_t mid, const coap_endpoint_t *ep);
void coap_send_transaction(coap_transaction_t *t);
void coap_clear_transaction(coap_transaction_t *t);
coap_transaction_t *coap_get_transaction_by_mid(uint16_t mid);
void coap_check_transactions(void);
#endif /* COAP_TRANSACTIONS_H_ */
/** @} */

Some files were not shown because too many files have changed in this diff Show More