client version of coap
Dependencies: nRF24L01P cantcoap3
coapClient.cpp@5:d633e12f113f, 2019-01-25 (annotated)
- Committer:
- Ka_myk
- Date:
- Fri Jan 25 12:10:49 2019 +0000
- Revision:
- 5:d633e12f113f
- Parent:
- 4:792cf53a73c4
all mains;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Ka_myk | 0:6a6f97ca5572 | 1 | // |
Ka_myk | 0:6a6f97ca5572 | 2 | // Created by Kamil Mykitiuk on 2019-01-17. |
Ka_myk | 0:6a6f97ca5572 | 3 | // |
Ka_myk | 0:6a6f97ca5572 | 4 | |
Ka_myk | 1:1d936c763440 | 5 | #include "coapClient.h" |
Ka_myk | 2:e8823d9fa162 | 6 | #include "dbg.h" |
Ka_myk | 0:6a6f97ca5572 | 7 | |
Ka_myk | 0:6a6f97ca5572 | 8 | bool match_uri(CoapPDU& coapPDU, char* uri) { |
Ka_myk | 0:6a6f97ca5572 | 9 | char respone_uri[32]; |
Ka_myk | 0:6a6f97ca5572 | 10 | int len = 0; |
Ka_myk | 0:6a6f97ca5572 | 11 | coapPDU.getURI(respone_uri, 32, &len); |
Ka_myk | 0:6a6f97ca5572 | 12 | return strcmp(uri, respone_uri) == 0; |
Ka_myk | 0:6a6f97ca5572 | 13 | } |
Ka_myk | 0:6a6f97ca5572 | 14 | |
Ka_myk | 0:6a6f97ca5572 | 15 | |
Ka_myk | 1:1d936c763440 | 16 | bool isExpectedResponse(CoapPDU& response, uint16_t message_id, char* uri) { |
Ka_myk | 0:6a6f97ca5572 | 17 | return match_uri(response, uri) && response.getType() == CoapPDU::COAP_ACKNOWLEDGEMENT && |
Ka_myk | 0:6a6f97ca5572 | 18 | response.getMessageID() == message_id; |
Ka_myk | 0:6a6f97ca5572 | 19 | } |
Ka_myk | 0:6a6f97ca5572 | 20 | |
Ka_myk | 1:1d936c763440 | 21 | bool CoapClient::isAck(CoapPDU& response, uint16_t message_id, char* uri) { |
Ka_myk | 0:6a6f97ca5572 | 22 | if (response.validate()) { |
Ka_myk | 4:792cf53a73c4 | 23 | response.printHuman(); |
Ka_myk | 5:d633e12f113f | 24 | DBG("WANNA: %d %s", message_id, uri); |
Ka_myk | 0:6a6f97ca5572 | 25 | if (isExpectedResponse(response, message_id, uri)) { |
Ka_myk | 0:6a6f97ca5572 | 26 | return true; |
Ka_myk | 0:6a6f97ca5572 | 27 | } |
Ka_myk | 0:6a6f97ca5572 | 28 | } |
Ka_myk | 0:6a6f97ca5572 | 29 | return false; |
Ka_myk | 0:6a6f97ca5572 | 30 | } |
Ka_myk | 0:6a6f97ca5572 | 31 | |
Ka_myk | 2:e8823d9fa162 | 32 | bool CoapClient::hasGetResponse(CoapPDU& response) { |
Ka_myk | 2:e8823d9fa162 | 33 | return std::memcmp(response.getTokenPointer(), this->token, static_cast<size_t>(response.getTokenLength())) == 0 && |
Ka_myk | 2:e8823d9fa162 | 34 | response.getCode() == CoapPDU::COAP_CONTENT; |
Ka_myk | 2:e8823d9fa162 | 35 | } |
Ka_myk | 0:6a6f97ca5572 | 36 | |
Ka_myk | 2:e8823d9fa162 | 37 | bool CoapClient::hasPostResponse(CoapPDU& response) { |
Ka_myk | 2:e8823d9fa162 | 38 | return response.getCode() == CoapPDU::COAP_CREATED && |
Ka_myk | 2:e8823d9fa162 | 39 | std::memcmp(response.getTokenPointer(), this->token, static_cast<size_t>(response.getTokenLength())) == 0; |
Ka_myk | 0:6a6f97ca5572 | 40 | } |
Ka_myk | 0:6a6f97ca5572 | 41 | |
Ka_myk | 2:e8823d9fa162 | 42 | |
Ka_myk | 0:6a6f97ca5572 | 43 | /* send get request to given uri of connected server |
Ka_myk | 0:6a6f97ca5572 | 44 | * |
Ka_myk | 0:6a6f97ca5572 | 45 | * @return number of saved bytes in provided buffer or |
Ka_myk | 0:6a6f97ca5572 | 46 | * -1 if server responded ambiguously; |
Ka_myk | 0:6a6f97ca5572 | 47 | * -2 if server timed out; |
Ka_myk | 0:6a6f97ca5572 | 48 | * -3 if provided buffer is to small to save response, |
Ka_myk | 0:6a6f97ca5572 | 49 | * -4 if if radio is not functioning properly |
Ka_myk | 0:6a6f97ca5572 | 50 | * */ |
Ka_myk | 0:6a6f97ca5572 | 51 | int CoapClient::get(uint8_t* buffer, int len, char* uri) { |
Ka_myk | 4:792cf53a73c4 | 52 | Timer t; |
Ka_myk | 0:6a6f97ca5572 | 53 | CoapPDU coapPDU = CoapPDU(); |
Ka_myk | 0:6a6f97ca5572 | 54 | uint16_t messageId = preparePDU(coapPDU); |
Ka_myk | 5:d633e12f113f | 55 | this->message_counter +=4; |
Ka_myk | 0:6a6f97ca5572 | 56 | coapPDU.setCode(CoapPDU::COAP_GET); |
Ka_myk | 0:6a6f97ca5572 | 57 | coapPDU.setURI(uri); |
Ka_myk | 0:6a6f97ca5572 | 58 | |
Ka_myk | 0:6a6f97ca5572 | 59 | uint8_t returnBuffer[radioWrapper.packetSize()]; |
Ka_myk | 4:792cf53a73c4 | 60 | int TIMEOUT = this->listeningTimeout; |
Ka_myk | 4:792cf53a73c4 | 61 | int timeout = TIMEOUT; |
Ka_myk | 0:6a6f97ca5572 | 62 | for (int i = 0; i < this->retransmissionLimit; i++) { |
Ka_myk | 4:792cf53a73c4 | 63 | while (timeout > 0) { |
Ka_myk | 4:792cf53a73c4 | 64 | int ret = radioWrapper.write(coapPDU.getPDUPointer(), coapPDU.getPDULength()); // send empty payload to get uri |
Ka_myk | 4:792cf53a73c4 | 65 | if (ret < 0) { |
Ka_myk | 4:792cf53a73c4 | 66 | return RADIO_NOT_WORKING; |
Ka_myk | 4:792cf53a73c4 | 67 | } |
Ka_myk | 4:792cf53a73c4 | 68 | t.start(); |
Ka_myk | 4:792cf53a73c4 | 69 | int readLen = radioWrapper.read(returnBuffer, radioWrapper.packetSize(), timeout); // add timeout param |
Ka_myk | 4:792cf53a73c4 | 70 | t.stop(); |
Ka_myk | 4:792cf53a73c4 | 71 | timeout -= t.read_ms(); |
Ka_myk | 4:792cf53a73c4 | 72 | t.reset(); |
Ka_myk | 4:792cf53a73c4 | 73 | if (readLen > 0) { // if something is recieved process it |
Ka_myk | 4:792cf53a73c4 | 74 | CoapPDU response(returnBuffer, len, readLen); |
Ka_myk | 4:792cf53a73c4 | 75 | if (isAck(response, messageId, uri) && hasGetResponse(response)) { |
Ka_myk | 4:792cf53a73c4 | 76 | DBG("RESPONSE: %d", readLen); |
Ka_myk | 4:792cf53a73c4 | 77 | response.printHuman(); |
Ka_myk | 4:792cf53a73c4 | 78 | if (response.getPayloadLength() <= len) { |
Ka_myk | 4:792cf53a73c4 | 79 | std::memcpy(buffer, response.getPayloadPointer(), |
Ka_myk | 4:792cf53a73c4 | 80 | static_cast<size_t>(response.getPayloadLength())); |
Ka_myk | 4:792cf53a73c4 | 81 | return response.getPayloadLength(); |
Ka_myk | 4:792cf53a73c4 | 82 | } else { |
Ka_myk | 4:792cf53a73c4 | 83 | return SMALL_BUFFER; |
Ka_myk | 4:792cf53a73c4 | 84 | } |
Ka_myk | 4:792cf53a73c4 | 85 | } else { |
Ka_myk | 4:792cf53a73c4 | 86 | DBG("NIEMOJE"); |
Ka_myk | 4:792cf53a73c4 | 87 | DBG("PAYLOAD: %s", response.getPayloadPointer()); |
Ka_myk | 4:792cf53a73c4 | 88 | continue; |
Ka_myk | 4:792cf53a73c4 | 89 | } |
Ka_myk | 4:792cf53a73c4 | 90 | } else if (readLen < 0) { |
Ka_myk | 4:792cf53a73c4 | 91 | return RADIO_NOT_WORKING; |
Ka_myk | 4:792cf53a73c4 | 92 | } |
Ka_myk | 0:6a6f97ca5572 | 93 | } |
Ka_myk | 4:792cf53a73c4 | 94 | TIMEOUT *= 2; |
Ka_myk | 4:792cf53a73c4 | 95 | timeout = TIMEOUT; |
Ka_myk | 0:6a6f97ca5572 | 96 | } |
Ka_myk | 2:e8823d9fa162 | 97 | |
Ka_myk | 2:e8823d9fa162 | 98 | return |
Ka_myk | 2:e8823d9fa162 | 99 | SERVER_TIMED_OUT; |
Ka_myk | 0:6a6f97ca5572 | 100 | } |
Ka_myk | 0:6a6f97ca5572 | 101 | |
Ka_myk | 0:6a6f97ca5572 | 102 | /* send post request to given uri of connected server |
Ka_myk | 0:6a6f97ca5572 | 103 | * |
Ka_myk | 0:6a6f97ca5572 | 104 | * @return 0 if operation has been completed successfully |
Ka_myk | 0:6a6f97ca5572 | 105 | * -1 if server responded ambiguously; |
Ka_myk | 0:6a6f97ca5572 | 106 | * -2 if server timed out; |
Ka_myk | 0:6a6f97ca5572 | 107 | * -4 if radio is not working properly |
Ka_myk | 0:6a6f97ca5572 | 108 | * */ |
Ka_myk | 0:6a6f97ca5572 | 109 | int CoapClient::post(uint8_t* buffer, int len, char* uri) { |
Ka_myk | 4:792cf53a73c4 | 110 | Timer t; |
Ka_myk | 0:6a6f97ca5572 | 111 | CoapPDU coapPDU = CoapPDU(); |
Ka_myk | 0:6a6f97ca5572 | 112 | uint16_t messageId = preparePDU(coapPDU); |
Ka_myk | 5:d633e12f113f | 113 | this->message_counter +=4; |
Ka_myk | 0:6a6f97ca5572 | 114 | coapPDU.setCode(CoapPDU::COAP_POST); |
Ka_myk | 0:6a6f97ca5572 | 115 | |
Ka_myk | 0:6a6f97ca5572 | 116 | coapPDU.setURI(uri); |
Ka_myk | 0:6a6f97ca5572 | 117 | coapPDU.setPayload(buffer, len); |
Ka_myk | 0:6a6f97ca5572 | 118 | uint8_t returnBuffer[radioWrapper.packetSize()]; |
Ka_myk | 4:792cf53a73c4 | 119 | int TIMEOUT = this->listeningTimeout; |
Ka_myk | 4:792cf53a73c4 | 120 | int timeout = TIMEOUT; |
Ka_myk | 0:6a6f97ca5572 | 121 | for (int i = 0; i < this->retransmissionLimit; i++) { |
Ka_myk | 4:792cf53a73c4 | 122 | while(timeout > 0) { |
Ka_myk | 4:792cf53a73c4 | 123 | int ret = radioWrapper.write(coapPDU.getPDUPointer(), coapPDU.getPDULength()); |
Ka_myk | 4:792cf53a73c4 | 124 | if (ret < 0) { |
Ka_myk | 4:792cf53a73c4 | 125 | return RADIO_NOT_WORKING; |
Ka_myk | 4:792cf53a73c4 | 126 | } |
Ka_myk | 4:792cf53a73c4 | 127 | t.start(); |
Ka_myk | 4:792cf53a73c4 | 128 | int readLen = radioWrapper.read(returnBuffer, radioWrapper.packetSize(), timeout); // add timeout param |
Ka_myk | 4:792cf53a73c4 | 129 | t.stop(); |
Ka_myk | 4:792cf53a73c4 | 130 | timeout -= t.read_ms(); |
Ka_myk | 4:792cf53a73c4 | 131 | t.reset(); |
Ka_myk | 4:792cf53a73c4 | 132 | if (readLen > 0) { // if something is recieved process it |
Ka_myk | 4:792cf53a73c4 | 133 | CoapPDU response(returnBuffer, len, readLen); |
Ka_myk | 4:792cf53a73c4 | 134 | if (isAck(response, messageId, uri) && hasPostResponse(response)) { |
Ka_myk | 4:792cf53a73c4 | 135 | return 0; |
Ka_myk | 4:792cf53a73c4 | 136 | } else { // if server hasn't responded properly |
Ka_myk | 4:792cf53a73c4 | 137 | DBG("NIEMOJE"); |
Ka_myk | 4:792cf53a73c4 | 138 | DBG("PAYLOAD: %s", response.getPayloadPointer()); |
Ka_myk | 4:792cf53a73c4 | 139 | continue; |
Ka_myk | 4:792cf53a73c4 | 140 | } |
Ka_myk | 4:792cf53a73c4 | 141 | } else if (readLen < 0) { |
Ka_myk | 4:792cf53a73c4 | 142 | return RADIO_NOT_WORKING; |
Ka_myk | 4:792cf53a73c4 | 143 | } |
Ka_myk | 0:6a6f97ca5572 | 144 | } |
Ka_myk | 4:792cf53a73c4 | 145 | TIMEOUT *= 2; |
Ka_myk | 4:792cf53a73c4 | 146 | timeout = TIMEOUT; |
Ka_myk | 0:6a6f97ca5572 | 147 | } |
Ka_myk | 0:6a6f97ca5572 | 148 | return SERVER_TIMED_OUT; |
Ka_myk | 0:6a6f97ca5572 | 149 | } |
Ka_myk | 0:6a6f97ca5572 | 150 | |
Ka_myk | 0:6a6f97ca5572 | 151 | uint16_t CoapClient::preparePDU(CoapPDU& coapPDU) { |
Ka_myk | 0:6a6f97ca5572 | 152 | coapPDU.setVersion(1); |
Ka_myk | 0:6a6f97ca5572 | 153 | coapPDU.setType(CoapPDU::COAP_CONFIRMABLE); |
Ka_myk | 0:6a6f97ca5572 | 154 | coapPDU.setMessageID(this->message_counter); |
Ka_myk | 2:e8823d9fa162 | 155 | coapPDU.setToken(this->token, 1); |
Ka_myk | 5:d633e12f113f | 156 | return this->message_counter; |
Ka_myk | 0:6a6f97ca5572 | 157 | } |
Ka_myk | 0:6a6f97ca5572 | 158 | |
Ka_myk | 5:d633e12f113f | 159 | CoapClient::CoapClient(uint16_t counter, uint8_t* token, int retransmissionLimit, int timeout, int channel, unsigned long long rx_address, |
Ka_myk | 5:d633e12f113f | 160 | unsigned long long tx_address): |
Ka_myk | 2:e8823d9fa162 | 161 | listeningTimeout(timeout), retransmissionLimit(retransmissionLimit), |
Ka_myk | 5:d633e12f113f | 162 | radioWrapper(channel, rx_address, tx_address), message_counter(counter) { |
Ka_myk | 2:e8823d9fa162 | 163 | std::memcpy(this->token, token, 1); |
Ka_myk | 4:792cf53a73c4 | 164 | } |