├── src ├── coap │ └── coap.h ├── simple-coap.h └── simple-coap.cpp ├── library.properties ├── license.txt ├── examples ├── coaptest │ └── coaptest.ino └── coapserver │ └── coapserver.ino └── README.md /src/coap/coap.h: -------------------------------------------------------------------------------- 1 | #include "../coap.h" -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=coap 2 | version=0.2.5 3 | license=MIT 4 | author=hirotakaster 5 | url=https://github.com/hirotakaster/CoAP/ 6 | repository=https://github.com/hirotakaster/CoAP.git 7 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Hirotaka Niisato 2 | This software is released under the MIT License. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/coaptest/coaptest.ino: -------------------------------------------------------------------------------- 1 | #include "simple-coap.h" 2 | 3 | // CoAP client response callback 4 | void callback_response(CoapPacket &packet, IPAddress ip, int port); 5 | Coap coap; 6 | 7 | // CoAP client response callback 8 | void callback_response(CoapPacket &packet, IPAddress ip, int port) { 9 | Serial.println("[Coap Response got]"); 10 | 11 | char p[packet.payloadlen + 1]; 12 | memcpy(p, packet.payload, packet.payloadlen); 13 | p[packet.payloadlen] = NULL; 14 | 15 | Serial.println(p); 16 | } 17 | 18 | void setup() { 19 | Serial.begin(9600); 20 | 21 | // client response callback. 22 | // this endpoint is single callback. 23 | Serial.println("Setup Response Callback"); 24 | coap.response(callback_response); 25 | 26 | // start coap server/client 27 | coap.start(); 28 | } 29 | 30 | void loop() { 31 | // send GET or PUT coap request to CoAP server. 32 | // for test, use libcoap, microcoap server...etc 33 | // int msgid = coap.put(IPAddress(10, 0, 0, 1), 5683, "light", "1"); 34 | Serial.println("Send Request"); 35 | int msgid = coap.get(IPAddress(0, 0, 0, 0), 5683, "time"); 36 | 37 | delay(1000); 38 | coap.loop(); 39 | } 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CoAP client, server library for Spark Photon, Spark Core. 2 | CoAP simple server, client library for Particle Photon, Core. 3 | 4 | ## Source Code 5 | This lightweight library source code are only 2 files. simple-coap.cpp, simple-coap.h. 6 | 7 | ## Example 8 | Some sample sketches for Spark Core and Photon included(firmware/examples/). 9 | 10 | - coaptest.ino : simple request/response sample. 11 | - coapserver.ino : server endpoint url callback sample. 12 | 13 | ## How to use 14 | 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. 15 | 16 | git clone https://github.com/obgm/libcoap 17 | cd libcoap/ 18 | ./autogen.sh 19 | ./configure --disable-examples 20 | gcc -o coap-server ./examples/coap-server.c -I./include/coap/ -I. -L.libs -lcoap-1 -DWITH_POSIX 21 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.libs 22 | ./coap-server 23 | # next start Photon or Core, check the request/response. 24 | 25 | ## Arduino compatible 26 | This library is Arduino compatible. That's version is here. 27 | -------------------------------------------------------------------------------- /examples/coapserver/coapserver.ino: -------------------------------------------------------------------------------- 1 | #include "simple-coap.h" 2 | 3 | // CoAP server endpoint url callback 4 | void callback_light(CoapPacket &packet, IPAddress ip, int port); 5 | 6 | // CoAP client response callback 7 | void callback_response(CoapPacket &packet, IPAddress ip, int port); 8 | 9 | Coap coap; 10 | bool LEDSTATE; 11 | 12 | // CoAP server endpoint URL 13 | void callback_light(CoapPacket &packet, IPAddress ip, int port) { 14 | Serial.println("[Light] ON/OFF"); 15 | 16 | // send response 17 | char p[packet.payloadlen + 1]; 18 | memcpy(p, packet.payload, packet.payloadlen); 19 | p[packet.payloadlen] = NULL; 20 | 21 | String message(p); 22 | 23 | if (message.equals("0")) 24 | LEDSTATE = false; 25 | else if(message.equals("1")) 26 | LEDSTATE = true; 27 | 28 | if (LEDSTATE) { 29 | coap.sendResponse(ip, port, packet.messageid, "1"); 30 | RGB.color(255, 255, 255); 31 | } else { 32 | coap.sendResponse(ip, port, packet.messageid, "0"); 33 | RGB.color(0, 0, 0); 34 | } 35 | } 36 | 37 | // CoAP client response callback 38 | void callback_response(CoapPacket &packet, IPAddress ip, int port) { 39 | Serial.println("[Coap Response got]"); 40 | 41 | char p[packet.payloadlen + 1]; 42 | memcpy(p, packet.payload, packet.payloadlen); 43 | p[packet.payloadlen] = NULL; 44 | 45 | Serial.println(p); 46 | } 47 | 48 | void setup() { 49 | Serial.begin(9600); 50 | 51 | // LED Controll 52 | RGB.control(true); 53 | RGB.color(255, 255, 255); 54 | LEDSTATE = true; 55 | 56 | // add server url endpoints. 57 | // can add multiple endpoint urls. 58 | // exp) coap.server(callback_switch, "switch"); 59 | // coap.server(callback_env, "env/temp"); 60 | // coap.server(callback_env, "env/humidity"); 61 | Serial.println("Setup Callback Light"); 62 | coap.server(callback_light, "light"); 63 | 64 | // client response callback. 65 | // this endpoint is single callback. 66 | Serial.println("Setup Response Callback"); 67 | coap.response(callback_response); 68 | 69 | // start coap server/client 70 | coap.start(); 71 | } 72 | 73 | void loop() { 74 | // send GET or PUT coap request to CoAP server. 75 | // for test, use microcoap server...etc 76 | // int msgid = coap.put(IPAddress(10, 0, 0, 1), 5683, "light", "1"); 77 | Serial.println("Send Request"); 78 | int msgid = coap.get(IPAddress(0, 0, 0, 0), 5683, "time"); 79 | 80 | delay(1000); 81 | coap.loop(); 82 | } 83 | 84 | /* 85 | if you change LED, req/res test with coap-client(libcoap), run following. 86 | coap-client -m get coap://(photon ip addr)/light 87 | coap-client -e "1" -m put coap://(photon ip addr)/light 88 | coap-client -e "0" -m put coap://(photon ip addr)/light 89 | */ 90 | -------------------------------------------------------------------------------- /src/simple-coap.h: -------------------------------------------------------------------------------- 1 | /* 2 | CoAP library for Core/Photon. 3 | This software is released under the MIT License. 4 | Copyright (c) 2014 Hirotaka Niisato 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | #ifndef __SIMPLE_COAP_H__ 24 | #define __SIMPLE_COAP_H__ 25 | 26 | #undef min 27 | #undef max 28 | #include 29 | #include "spark_wiring_string.h" 30 | #include "spark_wiring_usbserial.h" 31 | #include "spark_wiring_udp.h" 32 | #include "spark_wiring_ipaddress.h" 33 | 34 | #define COAP_HEADER_SIZE 4 35 | #define COAP_OPTION_HEADER_SIZE 1 36 | #define COAP_PAYLOAD_MARKER 0xFF 37 | #define MAX_OPTION_NUM 10 38 | #define BUF_MAX_SIZE 50 39 | #define COAP_DEFAULT_PORT 5683 40 | 41 | #define RESPONSE_CODE(class, detail) ((class << 5) | (detail)) 42 | #define COAP_OPTION_DELTA(v, n) (v < 13 ? (*n = (0xFF & v)) : (v <= 0xFF + 13 ? (*n = 13) : (*n = 14))) 43 | 44 | typedef enum { 45 | COAP_CON = 0, 46 | COAP_NONCON = 1, 47 | COAP_ACK = 2, 48 | COAP_RESET = 3 49 | } COAP_TYPE; 50 | 51 | typedef enum { 52 | COAP_GET = 1, 53 | COAP_POST = 2, 54 | COAP_PUT = 3, 55 | COAP_DELETE = 4 56 | } COAP_METHOD; 57 | 58 | typedef enum { 59 | COAP_CREATED = RESPONSE_CODE(2, 1), 60 | COAP_DELETED = RESPONSE_CODE(2, 2), 61 | COAP_VALID = RESPONSE_CODE(2, 3), 62 | COAP_CHANGED = RESPONSE_CODE(2, 4), 63 | COAP_CONTENT = RESPONSE_CODE(2, 5), 64 | COAP_BAD_REQUEST = RESPONSE_CODE(4, 0), 65 | COAP_UNAUTHORIZED = RESPONSE_CODE(4, 1), 66 | COAP_BAD_OPTION = RESPONSE_CODE(4, 2), 67 | COAP_FORBIDDEN = RESPONSE_CODE(4, 3), 68 | COAP_NOT_FOUNT = RESPONSE_CODE(4, 4), 69 | COAP_METHOD_NOT_ALLOWD = RESPONSE_CODE(4, 5), 70 | COAP_NOT_ACCEPTABLE = RESPONSE_CODE(4, 6), 71 | COAP_PRECONDITION_FAILED = RESPONSE_CODE(4, 12), 72 | COAP_REQUEST_ENTITY_TOO_LARGE = RESPONSE_CODE(4, 13), 73 | COAP_UNSUPPORTED_CONTENT_FORMAT = RESPONSE_CODE(4, 15), 74 | COAP_INTERNAL_SERVER_ERROR = RESPONSE_CODE(5, 0), 75 | COAP_NOT_IMPLEMENTED = RESPONSE_CODE(5, 1), 76 | COAP_BAD_GATEWAY = RESPONSE_CODE(5, 2), 77 | COAP_SERVICE_UNAVALIABLE = RESPONSE_CODE(5, 3), 78 | COAP_GATEWAY_TIMEOUT = RESPONSE_CODE(5, 4), 79 | COAP_PROXYING_NOT_SUPPORTED = RESPONSE_CODE(5, 5) 80 | } COAP_RESPONSE_CODE; 81 | 82 | typedef enum { 83 | COAP_IF_MATCH = 1, 84 | COAP_URI_HOST = 3, 85 | COAP_E_TAG = 4, 86 | COAP_IF_NONE_MATCH = 5, 87 | COAP_URI_PORT = 7, 88 | COAP_LOCATION_PATH = 8, 89 | COAP_URI_PATH = 11, 90 | COAP_CONTENT_FORMAT = 12, 91 | COAP_MAX_AGE = 14, 92 | COAP_URI_QUERY = 15, 93 | COAP_ACCEPT = 17, 94 | COAP_LOCATION_QUERY = 20, 95 | COAP_PROXY_URI = 35, 96 | COAP_PROXY_SCHEME = 39 97 | } COAP_OPTION_NUMBER; 98 | 99 | typedef enum { 100 | COAP_NONE = -1, 101 | COAP_TEXT_PLAIN = 0, 102 | COAP_APPLICATION_LINK_FORMAT = 40, 103 | COAP_APPLICATION_XML = 41, 104 | COAP_APPLICATION_OCTET_STREAM = 42, 105 | COAP_APPLICATION_EXI = 47, 106 | COAP_APPLICATION_JSON = 50 107 | } COAP_CONTENT_TYPE; 108 | 109 | class CoapOption { 110 | public: 111 | uint8_t number; 112 | uint8_t length; 113 | uint8_t *buffer; 114 | }; 115 | 116 | class CoapPacket { 117 | public: 118 | uint8_t type; 119 | uint8_t code; 120 | uint8_t *token; 121 | uint8_t tokenlen; 122 | uint8_t *payload; 123 | uint8_t payloadlen; 124 | uint16_t messageid; 125 | 126 | uint8_t optionnum; 127 | CoapOption options[MAX_OPTION_NUM]; 128 | }; 129 | typedef void (*callback)(CoapPacket &, IPAddress, int); 130 | 131 | class Coap { 132 | private: 133 | UDP *_udp; 134 | std::map uri; 135 | callback resp; 136 | int _port; 137 | 138 | uint16_t sendPacket(CoapPacket &packet, IPAddress ip); 139 | uint16_t sendPacket(CoapPacket &packet, IPAddress ip, int port); 140 | int parseOption(CoapOption *option, uint16_t *running_delta, uint8_t **buf, size_t buflen); 141 | 142 | public: 143 | Coap(); 144 | bool start(); 145 | bool start(int port); 146 | void response(callback c) { resp = c; } 147 | 148 | void server(callback c, String url) { uri[url] = c; } 149 | uint16_t sendResponse(IPAddress ip, int port, uint16_t messageid); 150 | uint16_t sendResponse(IPAddress ip, int port, uint16_t messageid, char *payload); 151 | uint16_t sendResponse(IPAddress ip, int port, uint16_t messageid, char *payload, int payloadlen); 152 | 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); 153 | 154 | uint16_t get(IPAddress ip, int port, char *url); 155 | uint16_t put(IPAddress ip, int port, char *url, char *payload); 156 | uint16_t put(IPAddress ip, int port, char *url, char *payload, int payloadlen); 157 | 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); 158 | 159 | bool loop(); 160 | }; 161 | #endif 162 | -------------------------------------------------------------------------------- /src/simple-coap.cpp: -------------------------------------------------------------------------------- 1 | #include "simple-coap.h" 2 | #include "application.h" 3 | #define LOGGING 4 | 5 | 6 | Coap::Coap() { 7 | this->_udp = new UDP(); 8 | } 9 | 10 | bool Coap::start() { 11 | this->start(COAP_DEFAULT_PORT); 12 | return true; 13 | } 14 | 15 | bool Coap::start(int port) { 16 | this->_udp->begin(port); 17 | return true; 18 | } 19 | 20 | uint16_t Coap::sendPacket(CoapPacket &packet, IPAddress ip) { 21 | return this->sendPacket(packet, ip, COAP_DEFAULT_PORT); 22 | } 23 | 24 | uint16_t Coap::sendPacket(CoapPacket &packet, IPAddress ip, int port) { 25 | uint8_t buffer[BUF_MAX_SIZE]; 26 | uint8_t *p = buffer; 27 | uint16_t running_delta = 0; 28 | uint16_t packetSize = 0; 29 | 30 | // make coap packet base header 31 | *p = 0x01 << 6; 32 | *p |= (packet.type & 0x03) << 4; 33 | *p++ |= (packet.tokenlen & 0x0F); 34 | *p++ = packet.code; 35 | *p++ = (packet.messageid >> 8); 36 | *p++ = (packet.messageid & 0xFF); 37 | p = buffer + COAP_HEADER_SIZE; 38 | packetSize += 4; 39 | 40 | // make token 41 | if (packet.token != NULL && packet.tokenlen <= 0x0F) { 42 | memcpy(p, packet.token, packet.tokenlen); 43 | p += packet.tokenlen; 44 | packetSize += packet.tokenlen; 45 | } 46 | 47 | // make option header 48 | for (int i = 0; i < packet.optionnum; i++) { 49 | uint32_t optdelta; 50 | uint8_t len, delta; 51 | 52 | if (packetSize + 5 + packet.options[i].length >= BUF_MAX_SIZE) { 53 | return 0; 54 | } 55 | optdelta = packet.options[i].number - running_delta; 56 | COAP_OPTION_DELTA(optdelta, &delta); 57 | COAP_OPTION_DELTA((uint32_t)packet.options[i].length, &len); 58 | 59 | *p++ = (0xFF & (delta << 4 | len)); 60 | if (delta == 13) { 61 | *p++ = (optdelta - 13); 62 | packetSize++; 63 | } else if (delta == 14) { 64 | *p++ = ((optdelta - 269) >> 8); 65 | *p++ = (0xFF & (optdelta - 269)); 66 | packetSize+=2; 67 | } if (len == 13) { 68 | *p++ = (packet.options[i].length - 13); 69 | packetSize++; 70 | } else if (len == 14) { 71 | *p++ = (packet.options[i].length >> 8); 72 | *p++ = (0xFF & (packet.options[i].length - 269)); 73 | packetSize+=2; 74 | } 75 | 76 | memcpy(p, packet.options[i].buffer, packet.options[i].length); 77 | p += packet.options[i].length; 78 | packetSize += packet.options[i].length + 1; 79 | running_delta = packet.options[i].number; 80 | } 81 | 82 | // make payload 83 | if (packet.payloadlen > 0) { 84 | if ((packetSize + 1 + packet.payloadlen) >= BUF_MAX_SIZE) { 85 | return 0; 86 | } 87 | *p++ = 0xFF; 88 | memcpy(p, packet.payload, packet.payloadlen); 89 | packetSize += 1 + packet.payloadlen; 90 | } 91 | 92 | _udp->beginPacket(ip, port); 93 | _udp->write(buffer, packetSize); 94 | _udp->endPacket(); 95 | 96 | return packet.messageid; 97 | } 98 | 99 | uint16_t Coap::get(IPAddress ip, int port, char *url) { 100 | return this->send(ip, port, url, COAP_CON, COAP_GET, NULL, 0, NULL, 0); 101 | } 102 | 103 | uint16_t Coap::put(IPAddress ip, int port, char *url, char *payload) { 104 | return this->send(ip, port, url, COAP_CON, COAP_PUT, NULL, 0, (uint8_t *)payload, strlen(payload)); 105 | } 106 | 107 | uint16_t Coap::put(IPAddress ip, int port, char *url, char *payload, int payloadlen) { 108 | return this->send(ip, port, url, COAP_CON, COAP_PUT, NULL, 0, (uint8_t *)payload, payloadlen); 109 | } 110 | 111 | 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) { 112 | 113 | // make packet 114 | CoapPacket packet; 115 | 116 | packet.type = type; 117 | packet.code = method; 118 | packet.token = token; 119 | packet.tokenlen = tokenlen; 120 | packet.payload = payload; 121 | packet.payloadlen = payloadlen; 122 | packet.optionnum = 0; 123 | packet.messageid = rand(); 124 | 125 | // if more options? 126 | packet.options[packet.optionnum].buffer = (uint8_t *)url; 127 | packet.options[packet.optionnum].length = strlen(url); 128 | packet.options[packet.optionnum].number = COAP_URI_PATH; 129 | packet.optionnum++; 130 | 131 | // send packet 132 | return this->sendPacket(packet, ip, port); 133 | } 134 | 135 | int Coap::parseOption(CoapOption *option, uint16_t *running_delta, uint8_t **buf, size_t buflen) { 136 | uint8_t *p = *buf; 137 | uint8_t headlen = 1; 138 | uint16_t len, delta; 139 | 140 | if (buflen < headlen) return -1; 141 | 142 | delta = (p[0] & 0xF0) >> 4; 143 | len = p[0] & 0x0F; 144 | 145 | if (delta == 13) { 146 | headlen++; 147 | if (buflen < headlen) return -1; 148 | delta = p[1] + 13; 149 | p++; 150 | } else if (delta == 14) { 151 | headlen += 2; 152 | if (buflen < headlen) return -1; 153 | delta = ((p[1] << 8) | p[2]) + 269; 154 | p+=2; 155 | } else if (delta == 15) return -1; 156 | 157 | if (len == 13) { 158 | headlen++; 159 | if (buflen < headlen) return -1; 160 | len = p[1] + 13; 161 | p++; 162 | } else if (len == 14) { 163 | headlen += 2; 164 | if (buflen < headlen) return -1; 165 | len = ((p[1] << 8) | p[2]) + 269; 166 | p+=2; 167 | } else if (len == 15) 168 | return -1; 169 | 170 | if ((p + 1 + len) > (*buf + buflen)) return -1; 171 | option->number = delta + *running_delta; 172 | option->buffer = p+1; 173 | option->length = len; 174 | *buf = p + 1 + len; 175 | *running_delta += delta; 176 | 177 | return 0; 178 | } 179 | 180 | bool Coap::loop() { 181 | 182 | uint8_t buffer[BUF_MAX_SIZE]; 183 | int32_t packetlen = _udp->parsePacket(); 184 | 185 | while (packetlen > 0) { 186 | packetlen = _udp->read(buffer, packetlen >= BUF_MAX_SIZE ? BUF_MAX_SIZE : packetlen); 187 | 188 | CoapPacket packet; 189 | 190 | // parse coap packet header 191 | if (packetlen < COAP_HEADER_SIZE || (((buffer[0] & 0xC0) >> 6) != 1)) { 192 | packetlen = _udp->parsePacket(); 193 | continue; 194 | } 195 | 196 | packet.type = (buffer[0] & 0x30) >> 4; 197 | packet.tokenlen = buffer[0] & 0x0F; 198 | packet.code = buffer[1]; 199 | packet.messageid = 0xFF00 & (buffer[2] << 8); 200 | packet.messageid |= 0x00FF & buffer[3]; 201 | 202 | if (packet.tokenlen == 0) packet.token = NULL; 203 | else if (packet.tokenlen <= 8) packet.token = buffer + 4; 204 | else { 205 | packetlen = _udp->parsePacket(); 206 | continue; 207 | } 208 | 209 | // parse packet options/payload 210 | if (COAP_HEADER_SIZE + packet.tokenlen < packetlen) { 211 | int optionIndex = 0; 212 | uint16_t delta = 0; 213 | uint8_t *end = buffer + packetlen; 214 | uint8_t *p = buffer + COAP_HEADER_SIZE + packet.tokenlen; 215 | while(optionIndex < MAX_OPTION_NUM && *p != 0xFF && p < end) { 216 | packet.options[optionIndex]; 217 | if (0 != parseOption(&packet.options[optionIndex], &delta, &p, end-p)) 218 | return false; 219 | optionIndex++; 220 | } 221 | packet.optionnum = optionIndex; 222 | 223 | if (p+1 < end && *p == 0xFF) { 224 | packet.payload = p+1; 225 | packet.payloadlen = end-(p+1); 226 | } else { 227 | packet.payload = NULL; 228 | packet.payloadlen= 0; 229 | } 230 | } 231 | 232 | if (packet.type == COAP_ACK) { 233 | // call response function 234 | resp(packet, _udp->remoteIP(), _udp->remotePort()); 235 | 236 | } else if (packet.type == COAP_CON) { 237 | // call endpoint url function 238 | String url = ""; 239 | for (int i = 0; i < packet.optionnum; i++) { 240 | if (packet.options[i].number == COAP_URI_PATH && packet.options[i].length > 0) { 241 | char urlname[packet.options[i].length + 1]; 242 | memcpy(urlname, packet.options[i].buffer, packet.options[i].length); 243 | urlname[packet.options[i].length] = NULL; 244 | if(url.length() > 0) 245 | url += "/"; 246 | url += urlname; 247 | } 248 | } 249 | if (uri.find(url) == uri.end()) { 250 | sendResponse(_udp->remoteIP(), _udp->remotePort(), packet.messageid, NULL, 0, 251 | COAP_NOT_FOUNT, COAP_NONE, NULL, 0); 252 | } else { 253 | uri[url](packet, _udp->remoteIP(), _udp->remotePort()); 254 | } 255 | } 256 | 257 | // next packet 258 | packetlen = _udp->parsePacket(); 259 | } 260 | 261 | return true; 262 | } 263 | 264 | uint16_t Coap::sendResponse(IPAddress ip, int port, uint16_t messageid) { 265 | return this->sendResponse(ip, port, messageid, NULL, 0, COAP_CONTENT, COAP_TEXT_PLAIN, NULL, 0); 266 | } 267 | 268 | uint16_t Coap::sendResponse(IPAddress ip, int port, uint16_t messageid, char *payload) { 269 | return this->sendResponse(ip, port, messageid, payload, strlen(payload), COAP_CONTENT, COAP_TEXT_PLAIN, NULL, 0); 270 | } 271 | 272 | uint16_t Coap::sendResponse(IPAddress ip, int port, uint16_t messageid, char *payload, int payloadlen) { 273 | return this->sendResponse(ip, port, messageid, payload, payloadlen, COAP_CONTENT, COAP_TEXT_PLAIN, NULL, 0); 274 | } 275 | 276 | 277 | uint16_t Coap::sendResponse(IPAddress ip, int port, uint16_t messageid, char *payload, int payloadlen, 278 | COAP_RESPONSE_CODE code, COAP_CONTENT_TYPE type, uint8_t *token, int tokenlen) { 279 | // make packet 280 | CoapPacket packet; 281 | 282 | packet.type = COAP_ACK; 283 | packet.code = code; 284 | packet.token = token; 285 | packet.tokenlen = tokenlen; 286 | packet.payload = (uint8_t *)payload; 287 | packet.payloadlen = payloadlen; 288 | packet.optionnum = 0; 289 | packet.messageid = messageid; 290 | 291 | // if more options? 292 | char optionBuffer[2]; 293 | optionBuffer[0] = ((uint16_t)type & 0xFF00) >> 8; 294 | optionBuffer[1] = ((uint16_t)type & 0x00FF) ; 295 | packet.options[packet.optionnum].buffer = (uint8_t *)optionBuffer; 296 | packet.options[packet.optionnum].length = 2; 297 | packet.options[packet.optionnum].number = COAP_CONTENT_FORMAT; 298 | packet.optionnum++; 299 | 300 | return this->sendPacket(packet, ip, port); 301 | } 302 | 303 | --------------------------------------------------------------------------------