Coap Client and Server
Dependencies: DebugLib EthernetInterface cantcoap mbed-rtos
Fork of yeswecancoap by
YesWeCanCoap
Is a small coap client and server library for mbed based on the cantcoap library.
Import librarycantcoap
This is CoAP library with a focus on simplicity. It offers minimal CoAP PDU construction and decoding to and from byte buffers.
yeswecancoap server enables easy implementation of coap resources, each with a dedicated function. When the function is registered by the server, it will do the rest.
Coap server example
Repository: YesWeCanCoap-example
Coap client example
under construction
client.cpp@29:62113a57353b, 2015-11-17 (annotated)
- Committer:
- sillevl
- Date:
- Tue Nov 17 16:44:39 2015 +0000
- Revision:
- 29:62113a57353b
- Parent:
- 19:6414961fb98d
added method to get the ip address
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dwini | 8:0169da22e764 | 1 | #include "client.h" |
dwini | 10:77bd145ec06c | 2 | #include "response.h" |
dwini | 10:77bd145ec06c | 3 | #include "request.h" |
dwini | 8:0169da22e764 | 4 | |
dwini | 8:0169da22e764 | 5 | // Identifier is some trivial string used for console output |
dwini | 8:0169da22e764 | 6 | Client::Client(const char * server, const int port, std::string identifier) { |
dwini | 8:0169da22e764 | 7 | udp_socket.init(); |
dwini | 8:0169da22e764 | 8 | udp_socket.set_blocking(false, 1000); |
dwini | 8:0169da22e764 | 9 | new_token_id = 0; |
dwini | 8:0169da22e764 | 10 | coap_server.set_address(server, port); |
dwini | 8:0169da22e764 | 11 | this->identifier = identifier; |
dwini | 8:0169da22e764 | 12 | new_message_id = 0; |
dwini | 8:0169da22e764 | 13 | } |
dwini | 8:0169da22e764 | 14 | |
dwini | 8:0169da22e764 | 15 | // Respons handler can be left null if no content respons is expected |
dwini | 19:6414961fb98d | 16 | void Client::sendRequest(char* uri, void (*response_handler)(Request*, Response*), CoapPDU::Code method) { |
dwini | 8:0169da22e764 | 17 | |
dwini | 8:0169da22e764 | 18 | CoapPDU *req_pdu = new CoapPDU(); |
dwini | 8:0169da22e764 | 19 | |
dwini | 8:0169da22e764 | 20 | switch (method) { |
dwini | 19:6414961fb98d | 21 | case CoapPDU::COAP_GET: |
dwini | 8:0169da22e764 | 22 | req_pdu->setType(CoapPDU::COAP_CONFIRMABLE); |
dwini | 19:6414961fb98d | 23 | break; |
dwini | 19:6414961fb98d | 24 | case CoapPDU::COAP_POST: |
dwini | 19:6414961fb98d | 25 | req_pdu->setType(CoapPDU::COAP_CONFIRMABLE); |
dwini | 8:0169da22e764 | 26 | break; |
dwini | 8:0169da22e764 | 27 | } |
dwini | 19:6414961fb98d | 28 | req_pdu->setCode(method); |
dwini | 8:0169da22e764 | 29 | req_pdu->setMessageID(new_message_id++); |
dwini | 14:ce76110ecf4d | 30 | new_token_id++; |
dwini | 14:ce76110ecf4d | 31 | req_pdu->setToken((uint8_t *)&new_token_id, sizeof(new_token_id)); |
dwini | 8:0169da22e764 | 32 | req_pdu->setURI(uri, strlen(uri)); |
dwini | 8:0169da22e764 | 33 | |
dwini | 8:0169da22e764 | 34 | unsigned int retries = 5; |
dwini | 8:0169da22e764 | 35 | while (retries > 0 && udp_socket.sendTo(coap_server, (char *)(req_pdu->getPDUPointer()), req_pdu->getPDULength()) < 0) { |
dwini | 8:0169da22e764 | 36 | retries--; |
dwini | 8:0169da22e764 | 37 | } |
dwini | 8:0169da22e764 | 38 | |
dwini | 8:0169da22e764 | 39 | if (retries == 0) { |
dwini | 8:0169da22e764 | 40 | printf("UDP socket problem - Could not send PDU\r\n"); |
dwini | 8:0169da22e764 | 41 | return; |
dwini | 8:0169da22e764 | 42 | } else { |
dwini | 19:6414961fb98d | 43 | if (method == CoapPDU::COAP_GET) { // Or confirmable ... |
dwini | 8:0169da22e764 | 44 | // We need to save request and wait for respons of server |
sillevl | 13:6667e331c719 | 45 | ResourceRequest req = { new_token_id, uri, response_handler, method, req_pdu }; |
dwini | 8:0169da22e764 | 46 | requests.push_back(req); |
dwini | 8:0169da22e764 | 47 | } |
dwini | 8:0169da22e764 | 48 | } |
dwini | 8:0169da22e764 | 49 | } |
dwini | 8:0169da22e764 | 50 | |
dwini | 8:0169da22e764 | 51 | void Client::checkForResponse(void) { |
dwini | 8:0169da22e764 | 52 | |
dwini | 8:0169da22e764 | 53 | if (requests.size() > 0) { // responses still need to be received |
dwini | 8:0169da22e764 | 54 | |
dwini | 8:0169da22e764 | 55 | char buffer[256]; |
dwini | 8:0169da22e764 | 56 | // printf("\r\nChecking for response UDP packet...\r\n"); |
dwini | 8:0169da22e764 | 57 | |
dwini | 8:0169da22e764 | 58 | // Check for udp packet from endpoint |
dwini | 8:0169da22e764 | 59 | int size = udp_socket.receiveFrom(coap_server, buffer, sizeof(buffer)-1); |
dwini | 8:0169da22e764 | 60 | if (size > 0) { |
dwini | 8:0169da22e764 | 61 | buffer[size] = '\0'; |
dwini | 8:0169da22e764 | 62 | |
dwini | 8:0169da22e764 | 63 | char uriBuffer[32]; |
dwini | 8:0169da22e764 | 64 | int recvURILen; |
dwini | 8:0169da22e764 | 65 | int msgId; |
dwini | 8:0169da22e764 | 66 | uint32_t token; |
dwini | 8:0169da22e764 | 67 | |
dwini | 8:0169da22e764 | 68 | // Lets coap |
dwini | 8:0169da22e764 | 69 | CoapPDU *recvPDU = new CoapPDU((uint8_t*)buffer, 256, size); |
dwini | 8:0169da22e764 | 70 | if(recvPDU->validate()) { |
dwini | 8:0169da22e764 | 71 | recvPDU->getURI(uriBuffer, 32, &recvURILen); |
dwini | 8:0169da22e764 | 72 | msgId = recvPDU->getMessageID(); |
dwini | 8:0169da22e764 | 73 | |
dwini | 8:0169da22e764 | 74 | // Parse token |
dwini | 8:0169da22e764 | 75 | if (recvPDU->getTokenLength() == sizeof(new_token_id)) { |
dwini | 8:0169da22e764 | 76 | token = *((uint32_t*)recvPDU->getTokenPointer()); |
dwini | 8:0169da22e764 | 77 | } else if (recvPDU->getTokenLength() == 0) { // Server does not care about tokens ? |
dwini | 8:0169da22e764 | 78 | // Then we force to match with first request |
dwini | 8:0169da22e764 | 79 | token = requests[0].token_id; |
dwini | 8:0169da22e764 | 80 | } else { |
dwini | 8:0169da22e764 | 81 | printf("Invalid token length\r\n"); |
dwini | 8:0169da22e764 | 82 | delete recvPDU; |
dwini | 8:0169da22e764 | 83 | return; |
dwini | 8:0169da22e764 | 84 | } |
dwini | 8:0169da22e764 | 85 | } else { |
dwini | 8:0169da22e764 | 86 | printf("Invalid Coap PDU received\r\n"); |
dwini | 8:0169da22e764 | 87 | recvPDU->printHuman(); |
dwini | 8:0169da22e764 | 88 | delete recvPDU; |
dwini | 8:0169da22e764 | 89 | return; |
dwini | 8:0169da22e764 | 90 | } |
dwini | 8:0169da22e764 | 91 | |
dwini | 8:0169da22e764 | 92 | // Check for which request the response is meant |
dwini | 8:0169da22e764 | 93 | int i = 0; |
dwini | 8:0169da22e764 | 94 | while (i < requests.size() && requests[i].token_id != token) { |
dwini | 8:0169da22e764 | 95 | i++; |
dwini | 8:0169da22e764 | 96 | } |
dwini | 8:0169da22e764 | 97 | |
dwini | 8:0169da22e764 | 98 | if (i < requests.size()) { // Found |
dwini | 8:0169da22e764 | 99 | // [TODO] Here we should check if it's not a premature ACK !!!!!! |
dwini | 8:0169da22e764 | 100 | |
dwini | 8:0169da22e764 | 101 | // Call handler if one exists |
dwini | 8:0169da22e764 | 102 | if (requests[i].response_handler) { |
dwini | 10:77bd145ec06c | 103 | requests[i].response_handler((Request*)(requests[i].req_pdu), (Response*)recvPDU); |
dwini | 8:0169da22e764 | 104 | } |
dwini | 8:0169da22e764 | 105 | |
dwini | 8:0169da22e764 | 106 | delete requests[i].req_pdu; |
dwini | 8:0169da22e764 | 107 | requests.erase(requests.begin() + i); |
dwini | 8:0169da22e764 | 108 | } else { |
dwini | 8:0169da22e764 | 109 | printf("Respons for unknown request\r\n"); |
dwini | 8:0169da22e764 | 110 | recvPDU->printHuman(); |
dwini | 8:0169da22e764 | 111 | } |
dwini | 8:0169da22e764 | 112 | |
dwini | 8:0169da22e764 | 113 | delete recvPDU; |
dwini | 8:0169da22e764 | 114 | } |
dwini | 8:0169da22e764 | 115 | } |
dwini | 8:0169da22e764 | 116 | } |