From 3cf97f9cc8351212300710c94074fa2cfdfdbd9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Bia=C5=82on=CC=81?= Date: Mon, 26 Jan 2015 20:13:21 +0100 Subject: [PATCH 1/7] Stop clearing request's memory Clearing packetbuf wipes out data for the request packet. After memset the request token is lost and it cannot be copied to the response. --- microcoap.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/microcoap.ino b/microcoap.ino index 148b6ce..800a66b 100644 --- a/microcoap.ino +++ b/microcoap.ino @@ -83,7 +83,6 @@ void loop() coap_packet_t rsppkt; coap_handle_req(&scratch_buf, &pkt, &rsppkt); - memset(packetbuf, 0, UDP_TX_PACKET_MAX_SIZE); if (0 != (rc = coap_build(packetbuf, &rsplen, &rsppkt))) { Serial.print("coap_build failed rc="); From 594d78a4a07d99e5729fa1fadb5220f6cd605e49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Bia=C5=82on=CC=81?= Date: Fri, 9 Jan 2015 12:16:34 +0100 Subject: [PATCH 2/7] Connect sensors to the cloud --- Makefile | 2 +- coap.c | 32 +++++- coap.h | 9 +- endpoints.c | 113 -------------------- main-posix.c | 71 ------------- microcoap.ino | 289 ++++++++++++++++++++++++++++++++++++++------------ 6 files changed, 256 insertions(+), 260 deletions(-) delete mode 100644 endpoints.c delete mode 100644 main-posix.c diff --git a/Makefile b/Makefile index 8412c58..7191e05 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ all: - gcc -Wall -o coap endpoints.c main-posix.c coap.c -DDEBUG + gcc -Wall -o coap main-posix.c coap.c -DDEBUG clean: rm -f coap diff --git a/coap.c b/coap.c index 10f6cb8..31ce375 100644 --- a/coap.c +++ b/coap.c @@ -6,8 +6,8 @@ #include #include "coap.h" -extern void endpoint_setup(void); -extern const coap_endpoint_t endpoints[]; +//extern void endpoint_setup(void); +//extern const coap_endpoint_t endpoints[]; #ifdef DEBUG void coap_dumpHeader(coap_header_t *hdr) @@ -360,6 +360,18 @@ void coap_option_nibble(uint8_t value, uint8_t *nibble) } } +int coap_add_option(coap_packet_t *pkt, uint8_t num, const uint8_t *p, size_t len) +{ + if (pkt->numopts == MAXOPT) { + return 1; + } + coap_option_t *opt = &pkt->opts[pkt->numopts++]; + opt->num = num; + opt->buf.p = p; + opt->buf.len = len; + return 0; +} + int coap_make_response(coap_rw_buffer_t *scratch, coap_packet_t *pkt, const uint8_t *content, size_t content_len, uint8_t msgid_hi, uint8_t msgid_lo, const coap_buffer_t* tok, coap_responsecode_t rspcode, coap_content_type_t content_type) { pkt->hdr.ver = 0x01; @@ -389,14 +401,26 @@ int coap_make_response(coap_rw_buffer_t *scratch, coap_packet_t *pkt, const uint return 0; } +int coap_make_request(coap_packet_t *pkt) +{ + pkt->hdr.ver = 0x01; + pkt->hdr.t = COAP_TYPE_CON; + pkt->hdr.tkl = 0; + pkt->hdr.code = 2; + pkt->hdr.id[0] = 0; + pkt->hdr.id[1] = 0; + pkt->numopts = 0; + pkt->payload.len = 0; + return 0; +} + // FIXME, if this looked in the table at the path before the method then // it could more easily return 405 errors -int coap_handle_req(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt) +int coap_handle_req(const coap_endpoint_t *ep, coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt) { const coap_option_t *opt; uint8_t count; int i; - const coap_endpoint_t *ep = endpoints; while(NULL != ep->handler) { diff --git a/coap.h b/coap.h index 4205f3b..bc3a4fa 100644 --- a/coap.h +++ b/coap.h @@ -105,6 +105,7 @@ typedef enum COAP_CONTENTTYPE_NONE = -1, // bodge to allow us not to send option block COAP_CONTENTTYPE_TEXT_PLAIN = 0, COAP_CONTENTTYPE_APPLICATION_LINKFORMAT = 40, + COAP_CONTENTTYPE_OCTET_STREAM = 42 } coap_content_type_t; /////////////////////// @@ -152,10 +153,14 @@ const coap_option_t *coap_findOptions(const coap_packet_t *pkt, uint8_t num, uin int coap_build(uint8_t *buf, size_t *buflen, const coap_packet_t *pkt); void coap_dump(const uint8_t *buf, size_t buflen, bool bare); int coap_make_response(coap_rw_buffer_t *scratch, coap_packet_t *pkt, const uint8_t *content, size_t content_len, uint8_t msgid_hi, uint8_t msgid_lo, const coap_buffer_t* tok, coap_responsecode_t rspcode, coap_content_type_t content_type); -int coap_handle_req(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt); +int coap_handle_req(const coap_endpoint_t *ep, coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt); void coap_option_nibble(uint8_t value, uint8_t *nibble); void coap_setup(void); -void endpoint_setup(void); + +//void endpoint_setup(void); + +int coap_make_request(coap_packet_t *pkt); +int coap_add_option(coap_packet_t *pkt, uint8_t num, const uint8_t *p, size_t len); #ifdef __cplusplus } diff --git a/endpoints.c b/endpoints.c deleted file mode 100644 index ccc961b..0000000 --- a/endpoints.c +++ /dev/null @@ -1,113 +0,0 @@ -#include -#include -#include "coap.h" - -static char light = '0'; - -const uint16_t rsplen = 1500; -static char rsp[1500] = ""; -void build_rsp(void); - -#ifdef ARDUINO -#include "Arduino.h" -static int led = 6; -void endpoint_setup(void) -{ - pinMode(led, OUTPUT); - build_rsp(); -} -#else -#include -void endpoint_setup(void) -{ - build_rsp(); -} -#endif - -static const coap_endpoint_path_t path_well_known_core = {2, {".well-known", "core"}}; -static int handle_get_well_known_core(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) -{ - return coap_make_response(scratch, outpkt, (const uint8_t *)rsp, strlen(rsp), id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_APPLICATION_LINKFORMAT); -} - -static const coap_endpoint_path_t path_light = {1, {"light"}}; -static int handle_get_light(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) -{ - return coap_make_response(scratch, outpkt, (const uint8_t *)&light, 1, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN); -} - -static int handle_put_light(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) -{ - if (inpkt->payload.len == 0) - return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_BAD_REQUEST, COAP_CONTENTTYPE_TEXT_PLAIN); - if (inpkt->payload.p[0] == '1') - { - light = '1'; -#ifdef ARDUINO - digitalWrite(led, HIGH); -#else - printf("ON\n"); -#endif - return coap_make_response(scratch, outpkt, (const uint8_t *)&light, 1, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CHANGED, COAP_CONTENTTYPE_TEXT_PLAIN); - } - else - { - light = '0'; -#ifdef ARDUINO - digitalWrite(led, LOW); -#else - printf("OFF\n"); -#endif - return coap_make_response(scratch, outpkt, (const uint8_t *)&light, 1, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CHANGED, COAP_CONTENTTYPE_TEXT_PLAIN); - } -} - -const coap_endpoint_t endpoints[] = -{ - {COAP_METHOD_GET, handle_get_well_known_core, &path_well_known_core, "ct=40"}, - {COAP_METHOD_GET, handle_get_light, &path_light, "ct=0"}, - {COAP_METHOD_PUT, handle_put_light, &path_light, NULL}, - {(coap_method_t)0, NULL, NULL, NULL} -}; - -void build_rsp(void) -{ - uint16_t len = rsplen; - const coap_endpoint_t *ep = endpoints; - int i; - - len--; // Null-terminated string - - while(NULL != ep->handler) - { - if (NULL == ep->core_attr) { - ep++; - continue; - } - - if (0 < strlen(rsp)) { - strncat(rsp, ",", len); - len--; - } - - strncat(rsp, "<", len); - len--; - - for (i = 0; i < ep->path->count; i++) { - strncat(rsp, "/", len); - len--; - - strncat(rsp, ep->path->elems[i], len); - len -= strlen(ep->path->elems[i]); - } - - strncat(rsp, ">;", len); - len -= 2; - - strncat(rsp, ep->core_attr, len); - len -= strlen(ep->core_attr); - - ep++; - } -} - diff --git a/main-posix.c b/main-posix.c deleted file mode 100644 index dd73cf9..0000000 --- a/main-posix.c +++ /dev/null @@ -1,71 +0,0 @@ -#include -#include -#include -#include -#include - -#include "coap.h" - -#define PORT 5683 - -int main(int argc, char **argv) -{ - int fd; - struct sockaddr_in servaddr, cliaddr; - uint8_t buf[4096]; - uint8_t scratch_raw[4096]; - coap_rw_buffer_t scratch_buf = {scratch_raw, sizeof(scratch_raw)}; - - fd = socket(AF_INET,SOCK_DGRAM,0); - - bzero(&servaddr,sizeof(servaddr)); - servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = htonl(INADDR_ANY); - servaddr.sin_port = htons(PORT); - bind(fd,(struct sockaddr *)&servaddr, sizeof(servaddr)); - - endpoint_setup(); - - while(1) - { - int n, rc; - socklen_t len = sizeof(cliaddr); - coap_packet_t pkt; - - n = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&cliaddr, &len); -#ifdef DEBUG - printf("Received: "); - coap_dump(buf, n, true); - printf("\n"); -#endif - - if (0 != (rc = coap_parse(&pkt, buf, n))) - printf("Bad packet rc=%d\n", rc); - else - { - size_t rsplen = sizeof(buf); - coap_packet_t rsppkt; -#ifdef DEBUG - coap_dumpPacket(&pkt); -#endif - coap_handle_req(&scratch_buf, &pkt, &rsppkt); - - if (0 != (rc = coap_build(buf, &rsplen, &rsppkt))) - printf("coap_build failed rc=%d\n", rc); - else - { -#ifdef DEBUG - printf("Sending: "); - coap_dump(buf, rsplen, true); - printf("\n"); -#endif -#ifdef DEBUG - coap_dumpPacket(&rsppkt); -#endif - - sendto(fd, buf, rsplen, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr)); - } - } - } -} - diff --git a/microcoap.ino b/microcoap.ino index 800a66b..5041d34 100644 --- a/microcoap.ino +++ b/microcoap.ino @@ -1,98 +1,249 @@ /* -* WARNING - UDP_TX_PACKET_MAX_SIZE is hardcoded by Arduino to 24 bytes -* This limits the size of possible outbound UDP packets -*/ + * WARNING - UDP_TX_PACKET_MAX_SIZE is hardcoded by Arduino to 24 bytes + * This limits the size of possible outbound UDP packets + */ +#include #include #include #include #include +//#define UDP_TX_PACKET_MAX_SIZE 256 +#include #include "coap.h" +#include "DHT.h" #define PORT 5683 +#define PING_TIMEOUT 30000 + static uint8_t mac[] = {0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02}; +IPAddress ip(185, 38, 249, 75); // com1.telemetria-online.pl + EthernetClient client; EthernetUDP udp; uint8_t packetbuf[256]; static uint8_t scratch_raw[32]; static coap_rw_buffer_t scratch_buf = {scratch_raw, sizeof(scratch_raw)}; -void setup() +unsigned long last_request_timestamp = 0; + +int ldr = 0; +int led = 6; + +DHT dht(5, DHT22); + +void endpoint_setup(void) { - int i; - Serial.begin(9600); - while (!Serial) - { - ; // wait for serial port to connect. Needed for Leonardo only - } + pinMode(ldr, INPUT); + pinMode(led, OUTPUT); + digitalWrite(led, HIGH); + dht.begin(); +} - // start the Ethernet connection: - if (Ethernet.begin(mac) == 0) - { - Serial.println("Failed to configure Ethernet using DHCP"); - while(1); - } - Serial.print("My IP address: "); - for (i=0;i<4;i++) - { - Serial.print(Ethernet.localIP()[i], DEC); - Serial.print("."); - } - Serial.println(); - udp.begin(PORT); +uint8_t led_read(void) +{ + return digitalRead(led); +} + +void led_write(uint8_t v) +{ + digitalWrite(led, v); +} - coap_setup(); - endpoint_setup(); +size_t msgpack_write_uint8(uint8_t *buf, uint8_t v) +{ + buf[0] = 0xCC; + buf[1] = v; + return 2; } -void udp_send(const uint8_t *buf, int buflen) +size_t msgpack_write_uint16(uint8_t *buf, uint16_t v) { - udp.beginPacket(udp.remoteIP(), udp.remotePort()); - while(buflen--) - udp.write(*buf++); - udp.endPacket(); + buf[0] = 0xCD; + memcpy(buf + 1, &v, 2); + return 3; +} + +size_t msgpack_write_uint32(uint8_t *buf, uint32_t v) +{ + buf[0] = 0xCE; + memcpy(buf + 1, &v, 4); + return 5; +} + +static const coap_endpoint_path_t path_status = {1, {"s"}}; +static int handle_get_status(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) +{ + uint8_t v = 42; + uint8_t *p = scratch->p; + size_t sz = msgpack_write_uint8(p, v); + scratch->p += sz; + return coap_make_response(scratch, outpkt, p, sz, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_OCTET_STREAM); +} + +static const coap_endpoint_path_t path_uptime = {1, {"uptime"}}; +static int handle_get_uptime(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) +{ + uint32_t uptime = millis() / 1000; + uint32_t v = htonl(uptime); + uint8_t *p = scratch->p; + size_t sz = msgpack_write_uint32(p, v); + scratch->p += sz; + return coap_make_response(scratch, outpkt, p, sz, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_OCTET_STREAM); +} + +static const coap_endpoint_path_t path_led = {1, {"led"}}; +static int handle_get_led(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) +{ + uint8_t v = led_read(); + uint8_t *p = scratch->p; + size_t sz = msgpack_write_uint8(p, v); + scratch->p += sz; + return coap_make_response(scratch, outpkt, p, sz, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_OCTET_STREAM); +} + +static int handle_put_led(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) +{ + if (inpkt->payload.len == 0) { + return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_BAD_REQUEST, COAP_CONTENTTYPE_OCTET_STREAM); + } + uint8_t v = inpkt->payload.p[0]; + uint8_t *p = scratch->p; + size_t sz = msgpack_write_uint8(p, v); + scratch->p += sz; + led_write(v); + return coap_make_response(scratch, outpkt, p, sz, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CHANGED, COAP_CONTENTTYPE_OCTET_STREAM); +} + +static const coap_endpoint_path_t path_ldr = {1, {"ldr"}}; +static int handle_get_ldr(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) +{ + uint16_t v = htons(analogRead(ldr)); + uint8_t *p = scratch->p; + size_t sz = msgpack_write_uint16(p, v); + scratch->p += sz; + return coap_make_response(scratch, outpkt, p, sz, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_OCTET_STREAM); +} + +static const coap_endpoint_path_t path_temperature = {1, {"t"}}; +static int handle_get_temperature(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) +{ + int t = dht.readTemperature() * 100; + uint16_t v = htons(t); + uint8_t *p = scratch->p; + size_t sz = msgpack_write_uint16(p, v); + scratch->p += sz; + return coap_make_response(scratch, outpkt, p, sz, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_OCTET_STREAM); +} + +static const coap_endpoint_path_t path_humidity = {1, {"h"}}; +static int handle_get_humidity(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) +{ + int h = dht.readHumidity() * 100; + uint16_t v = htons(h); + uint8_t *p = scratch->p; + size_t sz = msgpack_write_uint16(p, v); + scratch->p += sz; + return coap_make_response(scratch, outpkt, p, sz, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_OCTET_STREAM); +} + +const coap_endpoint_t endpoints[] = +{ + {COAP_METHOD_GET, handle_get_status, &path_status, "ct=42"}, + {COAP_METHOD_GET, handle_get_uptime, &path_uptime, "ct=42"}, + {COAP_METHOD_GET, handle_get_led, &path_led, "ct=42"}, + {COAP_METHOD_PUT, handle_put_led, &path_led, NULL}, + {COAP_METHOD_GET, handle_get_ldr, &path_ldr, "ct=42"}, + {COAP_METHOD_GET, handle_get_temperature, &path_temperature, "ct=42"}, + {COAP_METHOD_GET, handle_get_humidity, &path_humidity, "ct=42"}, + {(coap_method_t)0, NULL, NULL, NULL} +}; + +void udp_send(IPAddress ip, uint16_t port, const uint8_t *buf, int buflen) +{ + udp.beginPacket(ip, port); + while(buflen--) { + udp.write(*buf++); + } + udp.endPacket(); +} + +void reboot() +{ + wdt_enable(WDTO_15MS); + for (;;) {} +} + +void setup() +{ + wdt_disable(); + Serial.begin(19200); + + if (Ethernet.begin(mac) == 0) { + reboot(); + } + + Serial.print(F("My IP address: ")); + Serial.println(Ethernet.localIP()); + + udp.begin(PORT); + + coap_setup(); + endpoint_setup(); + + char ep[] = "ep=42424242424242424242424242424242"; + int eplen = strlen(ep); + + coap_packet_t pkt; + coap_make_request(&pkt); + coap_add_option(&pkt, COAP_OPTION_URI_PATH, (const uint8_t *)"rd", 2); + coap_add_option(&pkt, COAP_OPTION_URI_QUERY, (const uint8_t *)ep, eplen); + + memset(packetbuf, 0, UDP_TX_PACKET_MAX_SIZE); + + int rc; + size_t len = sizeof(packetbuf); + if (0 != (rc = coap_build(packetbuf, &len, &pkt))) { + reboot(); + } else { + udp_send(ip, PORT, packetbuf, len); + last_request_timestamp = millis(); + } } void loop() { - int sz; - int rc; - coap_packet_t pkt; - int i; - - if ((sz = udp.parsePacket()) > 0) - { - udp.read(packetbuf, sizeof(packetbuf)); - - for (i=0;i