Skip to content

Commit

Permalink
Merge pull request #19 from rosetree/feature/cbor-response
Browse files Browse the repository at this point in the history
Respond with phydat as CBOR
  • Loading branch information
MatthiasBraeuer authored Dec 9, 2019
2 parents 77cf8bd + 6433196 commit ded17e3
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 6 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ USEMODULE += ps

USEMODULE += netstats_l2

# Include tinycbor for data representation
USEPKG += tinycbor
INCLUDE += $(RIOTPKG)/tinycbor/cbor.h

CFLAGS += -DGNRC_IPV6_NIB_CONF_SLAAC=1


Expand Down
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ sensors of the same type are ignored. More sensor types need to be
manually added to the code base. These paths can be used without
knowledge about the RIOT-intern type representation.

Returns `phydat_t` as CBOR; see below for more info.

### `/sensor`
The `/sensor` resource is reachable with an `GET` request. As payload
it needs the ID of a saul sensor type (as they are defined in
Expand All @@ -24,6 +26,8 @@ out of the box. However, the systems calling this resource, need
information about the RIOT-intern saul type IDs. This could be used by
other RIOT powered boards.

Returns `phydat_t` as CBOR; see below for more info.

[saul.h]: https://github.com/RIOT-OS/RIOT/blob/d42c032998e77e122380b3d270ceedb7fff48cda/drivers/include/saul.h#L74

### `/saul/cnt` and `/saul/dev` (incomplete)
Expand All @@ -36,6 +40,44 @@ The idea of these resources is, to offer similar functionality as the
- `/saul/dev` (POST) needs an ID as argument. Returns some information
about the sensor for that ID (name and type).

## Phydat in Concise Binary Object Representation (CBOR)

In all resources by sensor type, we return the [`phydat_t` struct][]
in the [CBOR][] data format. In the following code block, you can see
a [CBOR example][] of what could be returned for a temperature sensor:

```
A3 # map(3)
66 # text(6)
76616C756573 # "values"
81 # array(1)
19 0959 # unsigned(2393)
64 # text(4)
756E6974 # "unit"
02 # unsigned(2)
65 # text(5)
7363616C65 # "scale"
21 # negative(1)
```

If you want to use this resource, you can parse it to JSON. The
example above translates to the following JSON object:

``` json
{"values": [2393], "unit": 2, "scale": -2}
```

Please see the [list of CBOR implementations][] if you want to use
this resource. The documentation of the [`phydat_t` struct][]
explains, how these values have to be interpreted.

[`phydat_t` struct]: https://riot-os.org/api/structphydat__t.html

[cbor]: http://cbor.io/

[cbor example]: http://cbor.me/?bytes=A3(66(76616C756573)-81(19.0959)-64(756E6974)-02-65(7363616C65)-21)

[list of cbor implementations]: http://cbor.io/impls.html

## Build and Execute
Enter shell with board command (Phytec)
Expand Down
89 changes: 83 additions & 6 deletions saul_coap.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@
#include "saul_reg.h"
#include "fmt.h"
#include "net/gcoap.h"
#include "cbor.h"

static ssize_t _saul_cnt_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, void *ctx);
static ssize_t _saul_dev_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, void *ctx);
static ssize_t _saul_sensortype_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, void *ctx);
static ssize_t _saul_type_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, void *ctx);

CborError export_phydat_to_cbor(CborEncoder *encoder, uint8_t *cbor_buf, size_t buf_len, phydat_t data, int dim);

/* supported sense types, used for context pointer in coap_resource_t */
uint8_t class_servo = SAUL_ACT_SERVO;
uint8_t class_hum = SAUL_SENSE_HUM;
Expand All @@ -56,6 +59,8 @@ static gcoap_listener_t _listener = {
NULL
};

static uint8_t cbor_buf[64] = { 0 };

static ssize_t _saul_dev_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, void *ctx)
{
int pos = 0;
Expand Down Expand Up @@ -169,9 +174,10 @@ static ssize_t _saul_type_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, voi
phydat_t res;
int dim;
size_t resp_len;
CborEncoder encoder;

gcoap_resp_init(pdu, buf, len, COAP_CODE_CONTENT);
coap_opt_add_format(pdu, COAP_FORMAT_TEXT);
coap_opt_add_format(pdu, COAP_FORMAT_CBOR);
resp_len = coap_opt_finish(pdu, COAP_OPT_FINISH_PAYLOAD);

if (dev == NULL) {
Expand Down Expand Up @@ -199,15 +205,86 @@ static ssize_t _saul_type_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, voi
}
}

/* TODO: Take care of all values. */
/* for (uint8_t i = 0; i < dim; i++) {
} */
CborError cbor_err = export_phydat_to_cbor(&encoder, cbor_buf, sizeof(cbor_buf), res, dim);

/* write the response buffer with the request device value */
resp_len += fmt_u16_dec((char *)pdu->payload, res.val[0]);
size_t buf_size = cbor_encoder_get_buffer_size(&encoder, cbor_buf);

if (cbor_err == CborNoError && buf_size > 0 && pdu->payload_len >= buf_size) {
memcpy(pdu->payload, cbor_buf, buf_size);
resp_len += buf_size;
} else {
resp_len = gcoap_response(pdu, buf, len, COAP_CODE_INTERNAL_SERVER_ERROR);
}

memset(cbor_buf, 0, sizeof(cbor_buf));
return resp_len;
}

CborError export_phydat_to_cbor(CborEncoder *encoder, uint8_t *cbor_buf, size_t buf_len, phydat_t data, int dim)
{
CborEncoder mapEncoder, aryEncoder;
CborError err = CborNoError;

cbor_encoder_init(encoder, cbor_buf, buf_len, 0);
if (err != CborNoError) {
return err;
}

err = cbor_encoder_create_map(encoder, &mapEncoder, 3);
if (err != CborNoError) {
return err;
}

err = cbor_encode_text_stringz(&mapEncoder, "values");
if (err != CborNoError) {
return err;
}

err = cbor_encoder_create_array(&mapEncoder, &aryEncoder, dim);
if (err != CborNoError) {
return err;
}

for (uint8_t i = 0; i < dim; i++) {
err = cbor_encode_int(&aryEncoder, data.val[i]);
if (err != CborNoError) {
return err;
}
}

err = cbor_encoder_close_container(&mapEncoder, &aryEncoder);
if (err != CborNoError) {
return err;
}

err = cbor_encode_text_stringz(&mapEncoder, "unit");
if (err != CborNoError) {
return err;
}

err = cbor_encode_int(&mapEncoder, data.unit);
if (err != CborNoError) {
return err;
}

err = cbor_encode_text_stringz(&mapEncoder, "scale");
if (err != CborNoError) {
return err;
}

err = cbor_encode_int(&mapEncoder, data.scale);
if (err != CborNoError) {
return err;
}

err = cbor_encoder_close_container(encoder, &mapEncoder);
if (err != CborNoError) {
return err;
}

return CborNoError;
}

void saul_coap_init(void)
{
gcoap_register_listener(&_listener);
Expand Down

0 comments on commit ded17e3

Please sign in to comment.