Coap Client and Server

Dependencies:   DebugLib EthernetInterface cantcoap mbed-rtos

Dependents:   COAP coap

Fork of yeswecancoap by Sille Van Landschoot

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

Committer:
sillevl
Date:
2015-11-17
Revision:
29:62113a57353b
Parent:
19:6414961fb98d

File content as of revision 29:62113a57353b:

#include "client.h"
#include "response.h"
#include "request.h"

// Identifier is some trivial string used for console output
Client::Client(const char * server, const int port, std::string identifier) {
    udp_socket.init();
    udp_socket.set_blocking(false, 1000);
    new_token_id = 0;
    coap_server.set_address(server, port);
    this->identifier = identifier;
    new_message_id = 0;
}

// Respons handler can be left null if no content respons is expected
void Client::sendRequest(char* uri, void (*response_handler)(Request*, Response*), CoapPDU::Code method) {

    CoapPDU *req_pdu = new CoapPDU();
    
    switch (method) {
        case CoapPDU::COAP_GET:
            req_pdu->setType(CoapPDU::COAP_CONFIRMABLE);
            break;
        case CoapPDU::COAP_POST:
            req_pdu->setType(CoapPDU::COAP_CONFIRMABLE);
            break;
    }
    req_pdu->setCode(method);
    req_pdu->setMessageID(new_message_id++);
    new_token_id++;
    req_pdu->setToken((uint8_t *)&new_token_id, sizeof(new_token_id));
    req_pdu->setURI(uri, strlen(uri));

    unsigned int retries = 5;
    while (retries > 0 && udp_socket.sendTo(coap_server, (char *)(req_pdu->getPDUPointer()), req_pdu->getPDULength()) < 0) {
        retries--;
    }
    
    if (retries == 0) {
        printf("UDP socket problem - Could not send PDU\r\n");
        return;
    } else {
        if (method == CoapPDU::COAP_GET) {  // Or confirmable ...
            // We need to save request and wait for respons of server
            ResourceRequest req = { new_token_id, uri, response_handler, method, req_pdu };
            requests.push_back(req);
        }
    }
}

void Client::checkForResponse(void) {

    if (requests.size() > 0) {       // responses still need to be received

        char buffer[256];
        // printf("\r\nChecking for response UDP packet...\r\n");

        // Check for udp packet from endpoint
        int size = udp_socket.receiveFrom(coap_server, buffer, sizeof(buffer)-1);
        if (size > 0) {
            buffer[size] = '\0';
            
            char uriBuffer[32];
            int recvURILen;
            int msgId;
            uint32_t token;

            // Lets coap
            CoapPDU *recvPDU = new CoapPDU((uint8_t*)buffer, 256, size);
            if(recvPDU->validate()) {
                recvPDU->getURI(uriBuffer, 32, &recvURILen); 
                msgId = recvPDU->getMessageID();

                // Parse token
                if (recvPDU->getTokenLength() == sizeof(new_token_id)) {
                    token = *((uint32_t*)recvPDU->getTokenPointer());
                } else if (recvPDU->getTokenLength() == 0) {    // Server does not care about tokens ? 
                    // Then we force to match with first request
                    token = requests[0].token_id;
                } else {
                    printf("Invalid token length\r\n");
                    delete recvPDU;
                    return;
                }
            } else {
                printf("Invalid Coap PDU received\r\n");
                recvPDU->printHuman();
                delete recvPDU;
                return;
            }
            
            // Check for which request the response is meant
            int i = 0;
            while (i < requests.size() && requests[i].token_id != token) {
                i++;
            }

            if (i < requests.size()) {      // Found
                // [TODO] Here we should check if it's not a premature ACK !!!!!!
                
                // Call handler if one exists
                if (requests[i].response_handler) {
                    requests[i].response_handler((Request*)(requests[i].req_pdu), (Response*)recvPDU);
                }

                delete requests[i].req_pdu;
                requests.erase(requests.begin() + i);
            } else {
                printf("Respons for unknown request\r\n");
                recvPDU->printHuman();
            }

            delete recvPDU;
        }
    }
}