From 76f0eea4d7eb101c15f12c21b0e8a68edd118197 Mon Sep 17 00:00:00 2001 From: hirotakaster Date: Fri, 12 Feb 2016 16:04:08 +0900 Subject: [PATCH] update from https://github.com/hirotakaster/CoAP/blob/arduino. --- README.md | 33 ++- coap.cpp | 323 +++++++++++++++++++++++++++++ coap.h | 212 +++++++++++++++++++ examples/coapserver/coapserver.ino | 107 ++++++++++ examples/coaptest/coaptest.ino | 58 ++++++ keywords.txt | 23 ++ library.properties | 9 + license.txt | 21 ++ 8 files changed, 785 insertions(+), 1 deletion(-) create mode 100644 coap.cpp create mode 100644 coap.h create mode 100644 examples/coapserver/coapserver.ino create mode 100644 examples/coaptest/coaptest.ino create mode 100644 keywords.txt create mode 100644 library.properties create mode 100644 license.txt diff --git a/README.md b/README.md index 8f4c190..3d9a5b3 100644 --- a/README.md +++ b/README.md @@ -1 +1,32 @@ -# CoAP-library +# CoAP client, server library for Arduino. +CoAP simple server, client library for Arduino. + +## Source Code +This lightweight library source code are only 2 files. coap.cpp, coap.h. + +## Example +Some sample sketches for Arduino included(/examples/). + + - coaptest.ino : simple request/response sample. + - coapserver.ino : server endpoint url callback sample. + +## How to use +Download this source code branch zip file and extract to the Arduino libraries directory or checkout repository. Here is checkout on MacOS X. + + cd $HOME/Documents/Arduino/libraries/ + git clone https://github.com/hirotakaster/CoAP-simple-library + # restart Arduino IDE, you can find CoAP-simple-library examples. + +In this exmples need CoAP server libcoap or microcoap server for check the example program. There is setting the libcoap on Ubuntu Linux. But if there don't use CoAP server(request/reseponse), following setting don't be needed. + + git clone https://github.com/obgm/libcoap + cd libcoap/ + ./autogen.sh + ./configure --disable-examples + gcc -o coap-server ./examples/coap-server.c -I./include/coap/ -I. -L.libs -lcoap-1 -DWITH_POSIX + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.libs + ./coap-server + # next start Arduino and check the request/response. + +## Particle Photon, Core compatible +This library is Particle Photon, Core compatible. That's version is here. diff --git a/coap.cpp b/coap.cpp new file mode 100644 index 0000000..56d7941 --- /dev/null +++ b/coap.cpp @@ -0,0 +1,323 @@ +#include "coap.h" + +#if defined(ARDUINO) +#include "Arduino.h" +#elif defined(SPARK) +#include "application.h" +#endif + +#define LOGGING + + +Coap::Coap( +#if defined(ARDUINO) + UDP& udp +#endif +) { + +#if defined(ARDUINO) + this->_udp = &udp; +#elif defined(SPARK) + this->_udp = new UDP(); +#endif + +} + +bool Coap::start() { + this->start(COAP_DEFAULT_PORT); + return true; +} + +bool Coap::start(int port) { + this->_udp->begin(port); + return true; +} + +uint16_t Coap::sendPacket(CoapPacket &packet, IPAddress ip) { + return this->sendPacket(packet, ip, COAP_DEFAULT_PORT); +} + +uint16_t Coap::sendPacket(CoapPacket &packet, IPAddress ip, int port) { + uint8_t buffer[BUF_MAX_SIZE]; + uint8_t *p = buffer; + uint16_t running_delta = 0; + uint16_t packetSize = 0; + + // make coap packet base header + *p = 0x01 << 6; + *p |= (packet.type & 0x03) << 4; + *p++ |= (packet.tokenlen & 0x0F); + *p++ = packet.code; + *p++ = (packet.messageid >> 8); + *p++ = (packet.messageid & 0xFF); + p = buffer + COAP_HEADER_SIZE; + packetSize += 4; + + // make token + if (packet.token != NULL && packet.tokenlen <= 0x0F) { + memcpy(p, packet.token, packet.tokenlen); + p += packet.tokenlen; + packetSize += packet.tokenlen; + } + + // make option header + for (int i = 0; i < packet.optionnum; i++) { + uint32_t optdelta; + uint8_t len, delta; + + if (packetSize + 5 + packet.options[i].length >= BUF_MAX_SIZE) { + return 0; + } + optdelta = packet.options[i].number - running_delta; + COAP_OPTION_DELTA(optdelta, &delta); + COAP_OPTION_DELTA((uint32_t)packet.options[i].length, &len); + + *p++ = (0xFF & (delta << 4 | len)); + if (delta == 13) { + *p++ = (optdelta - 13); + packetSize++; + } else if (delta == 14) { + *p++ = ((optdelta - 269) >> 8); + *p++ = (0xFF & (optdelta - 269)); + packetSize+=2; + } if (len == 13) { + *p++ = (packet.options[i].length - 13); + packetSize++; + } else if (len == 14) { + *p++ = (packet.options[i].length >> 8); + *p++ = (0xFF & (packet.options[i].length - 269)); + packetSize+=2; + } + + memcpy(p, packet.options[i].buffer, packet.options[i].length); + p += packet.options[i].length; + packetSize += packet.options[i].length + 1; + running_delta = packet.options[i].number; + } + + // make payload + if (packet.payloadlen > 0) { + if ((packetSize + 1 + packet.payloadlen) >= BUF_MAX_SIZE) { + return 0; + } + *p++ = 0xFF; + memcpy(p, packet.payload, packet.payloadlen); + packetSize += 1 + packet.payloadlen; + } + + _udp->beginPacket(ip, port); + _udp->write(buffer, packetSize); + _udp->endPacket(); + + return packet.messageid; +} + +uint16_t Coap::get(IPAddress ip, int port, char *url) { + return this->send(ip, port, url, COAP_CON, COAP_GET, NULL, 0, NULL, 0); +} + +uint16_t Coap::put(IPAddress ip, int port, char *url, char *payload) { + return this->send(ip, port, url, COAP_CON, COAP_PUT, NULL, 0, (uint8_t *)payload, strlen(payload)); +} + +uint16_t Coap::put(IPAddress ip, int port, char *url, char *payload, int payloadlen) { + return this->send(ip, port, url, COAP_CON, COAP_PUT, NULL, 0, (uint8_t *)payload, payloadlen); +} + +uint16_t Coap::send(IPAddress ip, int port, char *url, COAP_TYPE type, COAP_METHOD method, uint8_t *token, uint8_t tokenlen, uint8_t *payload, uint32_t payloadlen) { + + // make packet + CoapPacket packet; + + packet.type = type; + packet.code = method; + packet.token = token; + packet.tokenlen = tokenlen; + packet.payload = payload; + packet.payloadlen = payloadlen; + packet.optionnum = 0; + packet.messageid = rand(); + + // if more options? + packet.options[packet.optionnum].buffer = (uint8_t *)url; + packet.options[packet.optionnum].length = strlen(url); + packet.options[packet.optionnum].number = COAP_URI_PATH; + packet.optionnum++; + + // send packet + return this->sendPacket(packet, ip, port); +} + +int Coap::parseOption(CoapOption *option, uint16_t *running_delta, uint8_t **buf, size_t buflen) { + uint8_t *p = *buf; + uint8_t headlen = 1; + uint16_t len, delta; + + if (buflen < headlen) return -1; + + delta = (p[0] & 0xF0) >> 4; + len = p[0] & 0x0F; + + if (delta == 13) { + headlen++; + if (buflen < headlen) return -1; + delta = p[1] + 13; + p++; + } else if (delta == 14) { + headlen += 2; + if (buflen < headlen) return -1; + delta = ((p[1] << 8) | p[2]) + 269; + p+=2; + } else if (delta == 15) return -1; + + if (len == 13) { + headlen++; + if (buflen < headlen) return -1; + len = p[1] + 13; + p++; + } else if (len == 14) { + headlen += 2; + if (buflen < headlen) return -1; + len = ((p[1] << 8) | p[2]) + 269; + p+=2; + } else if (len == 15) + return -1; + + if ((p + 1 + len) > (*buf + buflen)) return -1; + option->number = delta + *running_delta; + option->buffer = p+1; + option->length = len; + *buf = p + 1 + len; + *running_delta += delta; + + return 0; +} + +bool Coap::loop() { + + uint8_t buffer[BUF_MAX_SIZE]; + int32_t packetlen = _udp->parsePacket(); + + while (packetlen > 0) { + packetlen = _udp->read(buffer, packetlen >= BUF_MAX_SIZE ? BUF_MAX_SIZE : packetlen); + + CoapPacket packet; + + // parse coap packet header + if (packetlen < COAP_HEADER_SIZE || (((buffer[0] & 0xC0) >> 6) != 1)) { + packetlen = _udp->parsePacket(); + continue; + } + + packet.type = (buffer[0] & 0x30) >> 4; + packet.tokenlen = buffer[0] & 0x0F; + packet.code = buffer[1]; + packet.messageid = 0xFF00 & (buffer[2] << 8); + packet.messageid |= 0x00FF & buffer[3]; + + if (packet.tokenlen == 0) packet.token = NULL; + else if (packet.tokenlen <= 8) packet.token = buffer + 4; + else { + packetlen = _udp->parsePacket(); + continue; + } + + // parse packet options/payload + if (COAP_HEADER_SIZE + packet.tokenlen < packetlen) { + int optionIndex = 0; + uint16_t delta = 0; + uint8_t *end = buffer + packetlen; + uint8_t *p = buffer + COAP_HEADER_SIZE + packet.tokenlen; + while(optionIndex < MAX_OPTION_NUM && *p != 0xFF && p < end) { + packet.options[optionIndex]; + if (0 != parseOption(&packet.options[optionIndex], &delta, &p, end-p)) + return false; + optionIndex++; + } + packet.optionnum = optionIndex; + + if (p+1 < end && *p == 0xFF) { + packet.payload = p+1; + packet.payloadlen = end-(p+1); + } else { + packet.payload = NULL; + packet.payloadlen= 0; + } + } + + if (packet.type == COAP_ACK) { + // call response function + resp(packet, _udp->remoteIP(), _udp->remotePort()); + + } else if (packet.type == COAP_CON) { + // call endpoint url function + for (int i = 0; i < packet.optionnum; i++) { + if (packet.options[i].number == COAP_URI_PATH && packet.options[i].length > 0) { + char urlname[packet.options[i].length + 1]; + memcpy(urlname, packet.options[i].buffer, packet.options[i].length); + urlname[packet.options[i].length] = NULL; + String url = urlname; +#if defined(ARDUINO) + if (!uri.find(url)) { +#elif defined(SPARK) + if (uri.find(url) == uri.end()) { +#endif + sendResponse(_udp->remoteIP(), _udp->remotePort(), packet.messageid, NULL, 0, + COAP_NOT_FOUNT, COAP_NONE, NULL, 0); + } else { +#if defined(ARDUINO) + uri.find(url)(packet, _udp->remoteIP(), _udp->remotePort()); +#elif defined(SPARK) + uri[url](packet, _udp->remoteIP(), _udp->remotePort()); +#endif + } + } + } + } + + // next packet + packetlen = _udp->parsePacket(); + } + + return true; +} + +uint16_t Coap::sendResponse(IPAddress ip, int port, uint16_t messageid) { + this->sendResponse(ip, port, messageid, NULL, 0, COAP_CONTENT, COAP_TEXT_PLAIN, NULL, 0); +} + +uint16_t Coap::sendResponse(IPAddress ip, int port, uint16_t messageid, char *payload) { + this->sendResponse(ip, port, messageid, payload, strlen(payload), COAP_CONTENT, COAP_TEXT_PLAIN, NULL, 0); +} + +uint16_t Coap::sendResponse(IPAddress ip, int port, uint16_t messageid, char *payload, int payloadlen) { + this->sendResponse(ip, port, messageid, payload, payloadlen, COAP_CONTENT, COAP_TEXT_PLAIN, NULL, 0); +} + + +uint16_t Coap::sendResponse(IPAddress ip, int port, uint16_t messageid, char *payload, int payloadlen, + COAP_RESPONSE_CODE code, COAP_CONTENT_TYPE type, uint8_t *token, int tokenlen) { + // make packet + CoapPacket packet; + + packet.type = COAP_ACK; + packet.code = code; + packet.token = token; + packet.tokenlen = tokenlen; + packet.payload = (uint8_t *)payload; + packet.payloadlen = payloadlen; + packet.optionnum = 0; + packet.messageid = messageid; + + // if more options? + char optionBuffer[2]; + optionBuffer[0] = ((uint16_t)type & 0xFF00) >> 8; + optionBuffer[1] = ((uint16_t)type & 0x00FF) ; + packet.options[packet.optionnum].buffer = (uint8_t *)optionBuffer; + packet.options[packet.optionnum].length = 2; + packet.options[packet.optionnum].number = COAP_CONTENT_FORMAT; + packet.optionnum++; + + return this->sendPacket(packet, ip, port); +} + diff --git a/coap.h b/coap.h new file mode 100644 index 0000000..cb650c7 --- /dev/null +++ b/coap.h @@ -0,0 +1,212 @@ +/* +CoAP library for Core/Photon. +This software is released under the MIT License. +Copyright (c) 2014 Hirotaka Niisato +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#ifndef __SIMPLE_COAP_H__ +#define __SIMPLE_COAP_H__ + +#if defined(ARDUINO) +#include "Udp.h" +#define MAX_CALLBACK 10 +#elif defined(SPARK) +#undef min +#undef max +#include +#include "spark_wiring_string.h" +#include "spark_wiring_usbserial.h" +#include "spark_wiring_udp.h" +#include "spark_wiring_ipaddress.h" +#endif + +#define COAP_HEADER_SIZE 4 +#define COAP_OPTION_HEADER_SIZE 1 +#define COAP_PAYLOAD_MARKER 0xFF +#define MAX_OPTION_NUM 10 +#define BUF_MAX_SIZE 50 +#define COAP_DEFAULT_PORT 5683 + +#define RESPONSE_CODE(class, detail) ((class << 5) | (detail)) +#define COAP_OPTION_DELTA(v, n) (v < 13 ? (*n = (0xFF & v)) : (v <= 0xFF + 13 ? (*n = 13) : (*n = 14))) + +typedef enum { + COAP_CON = 0, + COAP_NONCON = 1, + COAP_ACK = 2, + COAP_RESET = 3 +} COAP_TYPE; + +typedef enum { + COAP_GET = 1, + COAP_POST = 2, + COAP_PUT = 3, + COAP_DELETE = 4 +} COAP_METHOD; + +typedef enum { + COAP_CREATED = RESPONSE_CODE(2, 1), + COAP_DELETED = RESPONSE_CODE(2, 2), + COAP_VALID = RESPONSE_CODE(2, 3), + COAP_CHANGED = RESPONSE_CODE(2, 4), + COAP_CONTENT = RESPONSE_CODE(2, 5), + COAP_BAD_REQUEST = RESPONSE_CODE(4, 0), + COAP_UNAUTHORIZED = RESPONSE_CODE(4, 1), + COAP_BAD_OPTION = RESPONSE_CODE(4, 2), + COAP_FORBIDDEN = RESPONSE_CODE(4, 3), + COAP_NOT_FOUNT = RESPONSE_CODE(4, 4), + COAP_METHOD_NOT_ALLOWD = RESPONSE_CODE(4, 5), + COAP_NOT_ACCEPTABLE = RESPONSE_CODE(4, 6), + COAP_PRECONDITION_FAILED = RESPONSE_CODE(4, 12), + COAP_REQUEST_ENTITY_TOO_LARGE = RESPONSE_CODE(4, 13), + COAP_UNSUPPORTED_CONTENT_FORMAT = RESPONSE_CODE(4, 15), + COAP_INTERNAL_SERVER_ERROR = RESPONSE_CODE(5, 0), + COAP_NOT_IMPLEMENTED = RESPONSE_CODE(5, 1), + COAP_BAD_GATEWAY = RESPONSE_CODE(5, 2), + COAP_SERVICE_UNAVALIABLE = RESPONSE_CODE(5, 3), + COAP_GATEWAY_TIMEOUT = RESPONSE_CODE(5, 4), + COAP_PROXYING_NOT_SUPPORTED = RESPONSE_CODE(5, 5) +} COAP_RESPONSE_CODE; + +typedef enum { + COAP_IF_MATCH = 1, + COAP_URI_HOST = 3, + COAP_E_TAG = 4, + COAP_IF_NONE_MATCH = 5, + COAP_URI_PORT = 7, + COAP_LOCATION_PATH = 8, + COAP_URI_PATH = 11, + COAP_CONTENT_FORMAT = 12, + COAP_MAX_AGE = 14, + COAP_URI_QUERY = 15, + COAP_ACCEPT = 17, + COAP_LOCATION_QUERY = 20, + COAP_PROXY_URI = 35, + COAP_PROXY_SCHEME = 39 +} COAP_OPTION_NUMBER; + +typedef enum { + COAP_NONE = -1, + COAP_TEXT_PLAIN = 0, + COAP_APPLICATION_LINK_FORMAT = 40, + COAP_APPLICATION_XML = 41, + COAP_APPLICATION_OCTET_STREAM = 42, + COAP_APPLICATION_EXI = 47, + COAP_APPLICATION_JSON = 50 +} COAP_CONTENT_TYPE; + +class CoapOption { + public: + uint8_t number; + uint8_t length; + uint8_t *buffer; +}; + +class CoapPacket { + public: + uint8_t type; + uint8_t code; + uint8_t *token; + uint8_t tokenlen; + uint8_t *payload; + uint8_t payloadlen; + uint16_t messageid; + + uint8_t optionnum; + CoapOption options[MAX_OPTION_NUM]; +}; +typedef void (*callback)(CoapPacket &, IPAddress, int); + +#if defined(ARDUINO) +class CoapUri { + private: + String u[MAX_CALLBACK]; + callback c[MAX_CALLBACK]; + public: + CoapUri() { + for (int i = 0; i < MAX_CALLBACK; i++) { + u[i] = ""; + c[i] = NULL; + } + }; + void add(callback call, String url) { + for (int i = 0; i < MAX_CALLBACK; i++) + if (c[i] != NULL && u[i].equals(url)) { + c[i] = call; + return ; + } + for (int i = 0; i < MAX_CALLBACK; i++) { + if (c[i] == NULL) { + c[i] = call; + u[i] = url; + return; + } + } + }; + callback find(String url) { + for (int i = 0; i < MAX_CALLBACK; i++) if (c[i] != NULL && u[i].equals(url)) return c[i]; + return NULL; + } ; +}; +#endif + +class Coap { + private: + UDP *_udp; +#if defined(ARDUINO) + CoapUri uri; +#elif defined(SPARK) + std::map uri; +#endif + callback resp; + int _port; + + uint16_t sendPacket(CoapPacket &packet, IPAddress ip); + uint16_t sendPacket(CoapPacket &packet, IPAddress ip, int port); + int parseOption(CoapOption *option, uint16_t *running_delta, uint8_t **buf, size_t buflen); + + public: + Coap( +#if defined(ARDUINO) + UDP& udp +#endif + ); + bool start(); + bool start(int port); + void response(callback c) { resp = c; } + +#if defined(ARDUINO) + void server(callback c, String url) { uri.add(c, url); } +#elif defined(SPARK) + void server(callback c, String url) { uri[url] = c; } +#endif + uint16_t sendResponse(IPAddress ip, int port, uint16_t messageid); + uint16_t sendResponse(IPAddress ip, int port, uint16_t messageid, char *payload); + uint16_t sendResponse(IPAddress ip, int port, uint16_t messageid, char *payload, int payloadlen); + uint16_t sendResponse(IPAddress ip, int port, uint16_t messageid, char *payload, int payloadlen, COAP_RESPONSE_CODE code, COAP_CONTENT_TYPE type, uint8_t *token, int tokenlen); + + uint16_t get(IPAddress ip, int port, char *url); + uint16_t put(IPAddress ip, int port, char *url, char *payload); + uint16_t put(IPAddress ip, int port, char *url, char *payload, int payloadlen); + uint16_t send(IPAddress ip, int port, char *url, COAP_TYPE type, COAP_METHOD method, uint8_t *token, uint8_t tokenlen, uint8_t *payload, uint32_t payloadlen); + + bool loop(); +}; + +#endif diff --git a/examples/coapserver/coapserver.ino b/examples/coapserver/coapserver.ino new file mode 100644 index 0000000..d562154 --- /dev/null +++ b/examples/coapserver/coapserver.ino @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include + +byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 }; + +// CoAP client response callback +void callback_response(CoapPacket &packet, IPAddress ip, int port); + +// CoAP server endpoint url callback +void callback_light(CoapPacket &packet, IPAddress ip, int port); + +// UDP and CoAP class +EthernetUDP Udp; +Coap coap(Udp); + +// LED STATE +bool LEDSTATE; + +// CoAP server endpoint URL +void callback_light(CoapPacket &packet, IPAddress ip, int port) { + Serial.println("[Light] ON/OFF"); + + // send response + char p[packet.payloadlen + 1]; + memcpy(p, packet.payload, packet.payloadlen); + p[packet.payloadlen] = NULL; + + String message(p); + + if (message.equals("0")) + LEDSTATE = false; + else if(message.equals("1")) + LEDSTATE = true; + + if (LEDSTATE) { + digitalWrite(9, HIGH) ; + coap.sendResponse(ip, port, packet.messageid, "1"); + } else { + digitalWrite(9, LOW) ; + coap.sendResponse(ip, port, packet.messageid, "0"); + } +} + +// CoAP client response callback +void callback_response(CoapPacket &packet, IPAddress ip, int port) { + Serial.println("[Coap Response got]"); + + char p[packet.payloadlen + 1]; + memcpy(p, packet.payload, packet.payloadlen); + p[packet.payloadlen] = NULL; + + Serial.println(p); +} + +void setup() { + Serial.begin(9600); + + Ethernet.begin(mac); + Serial.print("My IP address: "); + for (byte thisByte = 0; thisByte < 4; thisByte++) { + Serial.print(Ethernet.localIP()[thisByte], DEC); + Serial.print("."); + } + Serial.println(); + + // LED State + pinMode(9, OUTPUT); + digitalWrite(9, HIGH); + LEDSTATE = true; + + // add server url endpoints. + // can add multiple endpoint urls. + // exp) coap.server(callback_switch, "switch"); + // coap.server(callback_env, "env/temp"); + // coap.server(callback_env, "env/humidity"); + Serial.println("Setup Callback Light"); + coap.server(callback_light, "light"); + + // client response callback. + // this endpoint is single callback. + Serial.println("Setup Response Callback"); + coap.response(callback_response); + + // start coap server/client + coap.start(); +} + +void loop() { + // send GET or PUT coap request to CoAP server. + // To test, use libcoap, microcoap server...etc + // int msgid = coap.put(IPAddress(10, 0, 0, 1), 5683, "light", "1"); + Serial.println("Send Request"); + int msgid = coap.get(IPAddress(XXX, XXX, XXX, XXX), 5683, "time"); + + delay(1000); + coap.loop(); +} +/* +if you change LED, req/res test with coap-client(libcoap), run following. +coap-client -m get coap://(arduino ip addr)/light +coap-client -e "1" -m put coap://(arduino ip addr)/light +coap-client -e "0" -m put coap://(arduino ip addr)/light +*/ diff --git a/examples/coaptest/coaptest.ino b/examples/coaptest/coaptest.ino new file mode 100644 index 0000000..5598920 --- /dev/null +++ b/examples/coaptest/coaptest.ino @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include + +byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 }; + +// CoAP client response callback +void callback_response(CoapPacket &packet, IPAddress ip, int port); + +// UDP and CoAP class +EthernetUDP Udp; +Coap coap(Udp); + +// CoAP client response callback +void callback_response(CoapPacket &packet, IPAddress ip, int port) { + Serial.println("[Coap Response got]"); + + char p[packet.payloadlen + 1]; + memcpy(p, packet.payload, packet.payloadlen); + p[packet.payloadlen] = NULL; + + Serial.println(p); +} + +void setup() { + Serial.begin(9600); + + Ethernet.begin(mac); + Serial.print("My IP address: "); + for (byte thisByte = 0; thisByte < 4; thisByte++) { + Serial.print(Ethernet.localIP()[thisByte], DEC); + Serial.print("."); + } + Serial.println(); + + + // client response callback. + // this endpoint is single callback. + Serial.println("Setup Response Callback"); + coap.response(callback_response); + + // start coap server/client + coap.start(); +} + +void loop() { + // send GET or PUT coap request to CoAP server. + // To test, use libcoap, microcoap server...etc + // int msgid = coap.put(IPAddress(10, 0, 0, 1), 5683, "light", "1"); + Serial.println("Send Request"); + int msgid = coap.get(IPAddress(XXX, XXX, XXX, XXX), 5683, "time"); + + delay(1000); + coap.loop(); +} diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..002c11f --- /dev/null +++ b/keywords.txt @@ -0,0 +1,23 @@ +####################################### +# Syntax Coloring Map For PubSubClient +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +CoAPSimpleLibrary KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +sendResponse KEYWORD2 +get KEYWORD2 +put KEYWORD2 +response KEYWORD2 +loop KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..3be8404 --- /dev/null +++ b/library.properties @@ -0,0 +1,9 @@ +name=CoAP simple library +version=1.3.5 +author=Hirotaka Niisato +maintainer=Hirotaka Niisato +sentence=Simple CoAP client/server library for generic Arduino Client hardware. +paragraph=This CoAP library support simple request/response message. +category=Communication +url=https://github.com/hirotakaster/CoAP-simple-library +architectures=* diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..e52552c --- /dev/null +++ b/license.txt @@ -0,0 +1,21 @@ +Copyright (c) 2015 Hirotaka Niisato +This software is released under the MIT License. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.