client version of coap

Dependencies:   nRF24L01P cantcoap3

Dependents:   client3

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers coapClient.cpp Source File

coapClient.cpp

00001 //
00002 // Created by Kamil Mykitiuk on 2019-01-17.
00003 //
00004 
00005 #include "coapClient.h"
00006 #include "dbg.h"
00007 
00008 bool match_uri(CoapPDU& coapPDU, char* uri) {
00009     char respone_uri[32];
00010     int len = 0;
00011     coapPDU.getURI(respone_uri, 32, &len);
00012     return strcmp(uri, respone_uri) == 0;
00013 }
00014 
00015 
00016 bool isExpectedResponse(CoapPDU& response, uint16_t message_id, char* uri) {
00017     return match_uri(response, uri) && response.getType() == CoapPDU::COAP_ACKNOWLEDGEMENT &&
00018            response.getMessageID() == message_id;
00019 }
00020 
00021 bool CoapClient::isAck(CoapPDU& response, uint16_t message_id, char* uri) {
00022     if (response.validate()) {
00023         response.printHuman();
00024         DBG("WANNA: %d %s", message_id, uri);
00025         if (isExpectedResponse(response, message_id, uri)) {
00026             return true;
00027         }
00028     }
00029     return false;
00030 }
00031 
00032 bool CoapClient::hasGetResponse(CoapPDU& response) {
00033     return std::memcmp(response.getTokenPointer(), this->token, static_cast<size_t>(response.getTokenLength())) == 0 &&
00034            response.getCode() == CoapPDU::COAP_CONTENT;
00035 }
00036 
00037 bool CoapClient::hasPostResponse(CoapPDU& response) {
00038     return response.getCode() == CoapPDU::COAP_CREATED &&
00039            std::memcmp(response.getTokenPointer(), this->token, static_cast<size_t>(response.getTokenLength())) == 0;
00040 }
00041 
00042 
00043 /* send get request to given uri of connected server
00044  *
00045  * @return number of saved bytes in provided buffer or
00046  * -1 if server responded ambiguously;
00047  * -2 if server timed out;
00048  * -3 if provided buffer is to small to save response,
00049  * -4 if if radio is not functioning properly
00050  * */
00051 int CoapClient::get(uint8_t* buffer, int len, char* uri) {
00052     Timer t;
00053     CoapPDU coapPDU = CoapPDU();
00054     uint16_t messageId = preparePDU(coapPDU);
00055     this->message_counter +=4;
00056     coapPDU.setCode(CoapPDU::COAP_GET);
00057     coapPDU.setURI(uri);
00058 
00059     uint8_t returnBuffer[radioWrapper.packetSize()];
00060     int TIMEOUT = this->listeningTimeout;
00061     int timeout = TIMEOUT;
00062     for (int i = 0; i < this->retransmissionLimit; i++) {
00063         while (timeout > 0) {
00064             int ret = radioWrapper.write(coapPDU.getPDUPointer(), coapPDU.getPDULength());  // send empty payload to get uri
00065             if (ret < 0) {
00066                 return RADIO_NOT_WORKING;
00067             }
00068             t.start();
00069             int readLen = radioWrapper.read(returnBuffer, radioWrapper.packetSize(), timeout); // add timeout param
00070             t.stop();
00071             timeout -= t.read_ms();
00072             t.reset();
00073             if (readLen > 0) { // if something is recieved process it
00074                 CoapPDU response(returnBuffer, len, readLen);
00075                 if (isAck(response, messageId, uri) && hasGetResponse(response)) {
00076                     DBG("RESPONSE: %d", readLen);
00077                     response.printHuman();
00078                     if (response.getPayloadLength() <= len) {
00079                         std::memcpy(buffer, response.getPayloadPointer(),
00080                                     static_cast<size_t>(response.getPayloadLength()));
00081                         return response.getPayloadLength();
00082                     } else {
00083                         return SMALL_BUFFER;
00084                     }
00085                 } else {
00086                     DBG("NIEMOJE");
00087                     DBG("PAYLOAD: %s", response.getPayloadPointer());
00088                     continue;
00089                 }
00090             } else if (readLen < 0) {
00091                 return RADIO_NOT_WORKING;
00092             }
00093         }
00094         TIMEOUT *= 2;
00095         timeout = TIMEOUT;
00096     }
00097 
00098     return
00099             SERVER_TIMED_OUT;
00100 }
00101 
00102 /* send post request to given uri of connected server
00103  *
00104  * @return 0 if operation has been completed successfully
00105  * -1 if server responded ambiguously;
00106  * -2 if server timed out;
00107  * -4 if radio is not working properly
00108  * */
00109 int CoapClient::post(uint8_t* buffer, int len, char* uri) {
00110     Timer t;
00111     CoapPDU coapPDU = CoapPDU();
00112     uint16_t messageId = preparePDU(coapPDU);
00113     this->message_counter +=4;
00114     coapPDU.setCode(CoapPDU::COAP_POST);
00115 
00116     coapPDU.setURI(uri);
00117     coapPDU.setPayload(buffer, len);
00118     uint8_t returnBuffer[radioWrapper.packetSize()];
00119     int TIMEOUT = this->listeningTimeout;
00120     int timeout = TIMEOUT;
00121     for (int i = 0; i < this->retransmissionLimit; i++) {
00122         while(timeout > 0) {
00123             int ret = radioWrapper.write(coapPDU.getPDUPointer(), coapPDU.getPDULength());
00124             if (ret < 0) {
00125                 return RADIO_NOT_WORKING;
00126             }
00127             t.start();
00128             int readLen = radioWrapper.read(returnBuffer, radioWrapper.packetSize(), timeout); // add timeout param
00129             t.stop();
00130             timeout -= t.read_ms();
00131             t.reset();
00132             if (readLen > 0) { // if something is recieved process it
00133                 CoapPDU response(returnBuffer, len, readLen);
00134                 if (isAck(response, messageId, uri) && hasPostResponse(response)) {
00135                     return 0;
00136                 } else { // if server hasn't responded properly
00137                     DBG("NIEMOJE");
00138                     DBG("PAYLOAD: %s", response.getPayloadPointer());
00139                     continue;
00140                 }
00141             } else if (readLen < 0) {
00142                 return RADIO_NOT_WORKING;
00143             }
00144         }
00145         TIMEOUT *= 2;
00146         timeout = TIMEOUT;
00147     }
00148     return SERVER_TIMED_OUT;
00149 }
00150 
00151 uint16_t CoapClient::preparePDU(CoapPDU& coapPDU) {
00152     coapPDU.setVersion(1);
00153     coapPDU.setType(CoapPDU::COAP_CONFIRMABLE);
00154     coapPDU.setMessageID(this->message_counter);
00155     coapPDU.setToken(this->token, 1);
00156     return this->message_counter;
00157 }
00158 
00159 CoapClient::CoapClient(uint16_t counter, uint8_t* token, int retransmissionLimit, int timeout, int channel, unsigned long long rx_address,
00160                        unsigned long long tx_address):
00161         listeningTimeout(timeout), retransmissionLimit(retransmissionLimit),
00162         radioWrapper(channel, rx_address, tx_address), message_counter(counter)  {
00163     std::memcpy(this->token, token, 1);
00164 }