Patrick Barrett / libexositecoap
Committer:
Patrick Barrett
Date:
Wed Jan 07 14:20:56 2015 -0600
Revision:
29:004c318e63fa
Parent:
27:786cdb9c3605
added retry on network error

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Patrick Barrett 0:c7393ae16c16 1 /*****************************************************************************
Patrick Barrett 0:c7393ae16c16 2 *
Patrick Barrett 0:c7393ae16c16 3 * exosite.c - Exosite Activator Library
Patrick Barrett 0:c7393ae16c16 4 * Copyright (C) 2015 Exosite LLC
Patrick Barrett 0:c7393ae16c16 5 *
Patrick Barrett 0:c7393ae16c16 6 * Redistribution and use in source and binary forms, with or without
Patrick Barrett 0:c7393ae16c16 7 * modification, are permitted provided that the following conditions
Patrick Barrett 0:c7393ae16c16 8 * are met:
Patrick Barrett 0:c7393ae16c16 9 *
Patrick Barrett 0:c7393ae16c16 10 * Redistributions of source code must retain the above copyright
Patrick Barrett 0:c7393ae16c16 11 * notice, this list of conditions and the following disclaimer.
Patrick Barrett 0:c7393ae16c16 12 *
Patrick Barrett 0:c7393ae16c16 13 * Redistributions in binary form must reproduce the above copyright
Patrick Barrett 0:c7393ae16c16 14 * notice, this list of conditions and the following disclaimer in the
Patrick Barrett 0:c7393ae16c16 15 * documentation and/or other materials provided with the
Patrick Barrett 0:c7393ae16c16 16 * distribution.
Patrick Barrett 0:c7393ae16c16 17 *
Patrick Barrett 0:c7393ae16c16 18 * Neither the name of Texas Instruments Incorporated nor the names of
Patrick Barrett 0:c7393ae16c16 19 * its contributors may be used to endorse or promote products derived
Patrick Barrett 0:c7393ae16c16 20 * from this software without specific prior written permission.
Patrick Barrett 0:c7393ae16c16 21 *
Patrick Barrett 0:c7393ae16c16 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Patrick Barrett 0:c7393ae16c16 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Patrick Barrett 0:c7393ae16c16 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Patrick Barrett 0:c7393ae16c16 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Patrick Barrett 0:c7393ae16c16 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Patrick Barrett 0:c7393ae16c16 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Patrick Barrett 0:c7393ae16c16 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Patrick Barrett 0:c7393ae16c16 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Patrick Barrett 0:c7393ae16c16 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Patrick Barrett 0:c7393ae16c16 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Patrick Barrett 0:c7393ae16c16 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Patrick Barrett 0:c7393ae16c16 33 *
Patrick Barrett 0:c7393ae16c16 34 *****************************************************************************/
Patrick Barrett 0:c7393ae16c16 35 #include "exosite_pal.h"
Patrick Barrett 0:c7393ae16c16 36 #include "exosite.h"
Patrick Barrett 0:c7393ae16c16 37 #include "coap.h"
Patrick Barrett 0:c7393ae16c16 38
Patrick Barrett 0:c7393ae16c16 39 #include <stdlib.h>
Patrick Barrett 0:c7393ae16c16 40 #include <stdbool.h>
Patrick Barrett 0:c7393ae16c16 41 #include <time.h>
Patrick Barrett 0:c7393ae16c16 42 #include <string.h>
Patrick Barrett 0:c7393ae16c16 43 #include <ctype.h>
Patrick Barrett 0:c7393ae16c16 44
Patrick Barrett 0:c7393ae16c16 45 // Internal Functions
Patrick Barrett 12:68513d2aa2df 46
Patrick Barrett 12:68513d2aa2df 47 static void exo_process_waiting_datagrams(exo_op *op, uint8_t count);
Patrick Barrett 12:68513d2aa2df 48 static void exo_process_active_ops(exo_op *op, uint8_t count);
Patrick Barrett 0:c7393ae16c16 49 exo_error exo_build_msg_activate(coap_pdu *pdu, const char *vendor, const char *model, const char *serial_number);
Patrick Barrett 0:c7393ae16c16 50 exo_error exo_build_msg_read(coap_pdu *pdu, const char *alias);
Patrick Barrett 0:c7393ae16c16 51 exo_error exo_build_msg_observe(coap_pdu *pdu, const char *alias);
Patrick Barrett 0:c7393ae16c16 52 exo_error exo_build_msg_write(coap_pdu *pdu, const char *alias, const char *value);
Patrick Barrett 0:c7393ae16c16 53 exo_error exo_build_msg_rst(coap_pdu *pdu, const uint16_t mid, const uint64_t token, const uint8_t tkl);
Patrick Barrett 0:c7393ae16c16 54 exo_error exo_build_msg_ack(coap_pdu *pdu, const uint16_t mid);
Patrick Barrett 0:c7393ae16c16 55 uint8_t exosite_validate_cik(char *cik);
Patrick Barrett 0:c7393ae16c16 56
Patrick Barrett 0:c7393ae16c16 57 // Local Variables
Patrick Barrett 0:c7393ae16c16 58 static char cik[CIK_LENGTH + 1];
Patrick Barrett 0:c7393ae16c16 59 static const char *vendor;
Patrick Barrett 0:c7393ae16c16 60 static const char *model;
Patrick Barrett 0:c7393ae16c16 61 static const char *serial;
Patrick Barrett 0:c7393ae16c16 62 static uint16_t message_id_counter;
Patrick Barrett 0:c7393ae16c16 63 static exo_device_state device_state = EXO_STATE_UNINITIALIZED;
Patrick Barrett 0:c7393ae16c16 64
Patrick Barrett 23:e94087cd483d 65 // Internal Constants
Patrick Barrett 23:e94087cd483d 66 static const int MINIMUM_DATAGRAM_SIZE = 576; // RFC791: all hosts must accept minimum of 576 octets
Patrick Barrett 23:e94087cd483d 67
Patrick Barrett 0:c7393ae16c16 68 /*!
Patrick Barrett 0:c7393ae16c16 69 * \brief Initializes the Exosite library
Patrick Barrett 0:c7393ae16c16 70 *
Patrick Barrett 0:c7393ae16c16 71 * This **MUST** be called before any other exosite library calls are called.
Patrick Barrett 0:c7393ae16c16 72 *
Patrick Barrett 0:c7393ae16c16 73 * \param[in] *vendor Pointer to string containing the vendor name
Patrick Barrett 0:c7393ae16c16 74 * \param[in] *model Pointer to string containing the model name
Patrick Barrett 0:c7393ae16c16 75 * \param[in] *serial Pointer to string containing the serial number
Patrick Barrett 0:c7393ae16c16 76 *
Patrick Barrett 0:c7393ae16c16 77 * \return EXO_ERROR, EXO_OK on success, else error code
Patrick Barrett 0:c7393ae16c16 78 */
Patrick Barrett 0:c7393ae16c16 79 exo_error exo_init(const char *vendor_in, const char *model_in, const char *serial_in)
Patrick Barrett 0:c7393ae16c16 80 {
Patrick Barrett 0:c7393ae16c16 81 device_state = EXO_STATE_UNINITIALIZED;
Patrick Barrett 0:c7393ae16c16 82
Patrick Barrett 0:c7393ae16c16 83 if (exopal_init() != 0) {
Patrick Barrett 0:c7393ae16c16 84 return EXO_FATAL_ERROR_PAL;
Patrick Barrett 0:c7393ae16c16 85 }
Patrick Barrett 0:c7393ae16c16 86
Patrick Barrett 0:c7393ae16c16 87 srand(time(NULL));
Patrick Barrett 0:c7393ae16c16 88 message_id_counter = rand();
Patrick Barrett 0:c7393ae16c16 89
Patrick Barrett 0:c7393ae16c16 90 serial = serial_in;
Patrick Barrett 0:c7393ae16c16 91 vendor = vendor_in;
Patrick Barrett 0:c7393ae16c16 92 model = model_in;
Patrick Barrett 0:c7393ae16c16 93
Patrick Barrett 0:c7393ae16c16 94 if (exopal_retrieve_cik(cik) > 1){
Patrick Barrett 0:c7393ae16c16 95 return EXO_FATAL_ERROR_PAL;
Patrick Barrett 0:c7393ae16c16 96 } else {
Patrick Barrett 0:c7393ae16c16 97 cik[40] = 0;
Patrick Barrett 0:c7393ae16c16 98 }
Patrick Barrett 0:c7393ae16c16 99
Patrick Barrett 0:c7393ae16c16 100 if (exopal_udp_sock() != 0) {
Patrick Barrett 0:c7393ae16c16 101 return EXO_FATAL_ERROR_PAL;
Patrick Barrett 0:c7393ae16c16 102 }
Patrick Barrett 0:c7393ae16c16 103
Patrick Barrett 0:c7393ae16c16 104 device_state = EXO_STATE_INITIALIZED;
Patrick Barrett 0:c7393ae16c16 105
Patrick Barrett 0:c7393ae16c16 106 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 107 }
Patrick Barrett 0:c7393ae16c16 108
Patrick Barrett 0:c7393ae16c16 109 /*!
Patrick Barrett 0:c7393ae16c16 110 * \brief Queues a Write to the Exosite One Platform
Patrick Barrett 0:c7393ae16c16 111 *
Patrick Barrett 0:c7393ae16c16 112 * Queues a request to write to a dataport.
Patrick Barrett 0:c7393ae16c16 113 *
Patrick Barrett 0:c7393ae16c16 114 * \param[in] *alias Alias of dataport to write to, pointer must remain
Patrick Barrett 0:c7393ae16c16 115 * valid until the request has been sent.
Patrick Barrett 0:c7393ae16c16 116 * \param[in] callback Function pointer to call on success
Patrick Barrett 0:c7393ae16c16 117 *
Patrick Barrett 0:c7393ae16c16 118 * \return EXO_ERROR, EXO_OK on success or error code
Patrick Barrett 0:c7393ae16c16 119 *
Patrick Barrett 0:c7393ae16c16 120 */
Patrick Barrett 0:c7393ae16c16 121
Patrick Barrett 0:c7393ae16c16 122 void exo_write(exo_op *op, const char * alias, const char * value)
Patrick Barrett 0:c7393ae16c16 123 {
Patrick Barrett 0:c7393ae16c16 124 op->type = EXO_WRITE;
Patrick Barrett 0:c7393ae16c16 125 op->state = EXO_REQUEST_NEW;
Patrick Barrett 0:c7393ae16c16 126 op->alias = alias;
Patrick Barrett 0:c7393ae16c16 127 op->value = (char *)value; // this is kinda dirty, I know
Patrick Barrett 0:c7393ae16c16 128 op->value_max = 0;
Patrick Barrett 0:c7393ae16c16 129 op->mid = 0;
Patrick Barrett 0:c7393ae16c16 130 }
Patrick Barrett 0:c7393ae16c16 131
Patrick Barrett 0:c7393ae16c16 132 /*!
Patrick Barrett 0:c7393ae16c16 133 * \brief Queues a Read from the Exosite One Platform
Patrick Barrett 0:c7393ae16c16 134 *
Patrick Barrett 0:c7393ae16c16 135 * Queues a request to read a dataport. If the request is successful, the
Patrick Barrett 0:c7393ae16c16 136 * provided callback will be called with a single parameter, a pointer to the
Patrick Barrett 0:c7393ae16c16 137 * result as a C string.
Patrick Barrett 0:c7393ae16c16 138 *
Patrick Barrett 0:c7393ae16c16 139 * \param[in] *alias Alias of dataport to read from, pointer must remain
Patrick Barrett 0:c7393ae16c16 140 * valid until the request has been sent.
Patrick Barrett 0:c7393ae16c16 141 * \param[in] callback Function pointer to call on success
Patrick Barrett 0:c7393ae16c16 142 *
Patrick Barrett 0:c7393ae16c16 143 * \return EXO_ERROR, EXO_OK on success or error code
Patrick Barrett 0:c7393ae16c16 144 *
Patrick Barrett 0:c7393ae16c16 145 */
Patrick Barrett 0:c7393ae16c16 146 void exo_read(exo_op *op, const char * alias, char * value, const size_t value_max)
Patrick Barrett 0:c7393ae16c16 147 {
Patrick Barrett 0:c7393ae16c16 148 op->type = EXO_READ;
Patrick Barrett 0:c7393ae16c16 149 op->state = EXO_REQUEST_NEW;
Patrick Barrett 0:c7393ae16c16 150 op->alias = alias;
Patrick Barrett 0:c7393ae16c16 151 op->value = value;
Patrick Barrett 0:c7393ae16c16 152 op->value_max = value_max;
Patrick Barrett 0:c7393ae16c16 153 op->mid = 0;
Patrick Barrett 0:c7393ae16c16 154 }
Patrick Barrett 0:c7393ae16c16 155
Patrick Barrett 0:c7393ae16c16 156 /*!
Patrick Barrett 0:c7393ae16c16 157 * \brief Subscribes to a Dataport on the Exosite One Platform
Patrick Barrett 0:c7393ae16c16 158 *
Patrick Barrett 0:c7393ae16c16 159 * Begins a subscription to a dataport The callback is called any time the
Patrick Barrett 0:c7393ae16c16 160 * value is updated as well as when the subscription is started.
Patrick Barrett 0:c7393ae16c16 161 *
Patrick Barrett 0:c7393ae16c16 162 * \param[in] alias Alias of dataport to read from
Patrick Barrett 0:c7393ae16c16 163 * \param[in] callback Function pointer to call on change
Patrick Barrett 0:c7393ae16c16 164 *
Patrick Barrett 0:c7393ae16c16 165 * \return EXO_ERROR, EXO_OK on success or error code
Patrick Barrett 0:c7393ae16c16 166 *
Patrick Barrett 0:c7393ae16c16 167 */
Patrick Barrett 0:c7393ae16c16 168 void exo_subscribe(exo_op *op, const char * alias, char * value, const size_t value_max)
Patrick Barrett 0:c7393ae16c16 169 {
Patrick Barrett 0:c7393ae16c16 170 op->type = EXO_SUBSCRIBE;
Patrick Barrett 0:c7393ae16c16 171 op->state = EXO_REQUEST_NEW;
Patrick Barrett 0:c7393ae16c16 172 op->alias = alias;
Patrick Barrett 0:c7393ae16c16 173 op->value = value;
Patrick Barrett 0:c7393ae16c16 174 op->value_max = value_max;
Patrick Barrett 0:c7393ae16c16 175 op->mid = 0;
Patrick Barrett 0:c7393ae16c16 176 }
Patrick Barrett 0:c7393ae16c16 177
Patrick Barrett 11:08bae8fb9824 178 /*!
Patrick Barrett 11:08bae8fb9824 179 * \brief Activates the Device on the Platform
Patrick Barrett 11:08bae8fb9824 180 *
Patrick Barrett 11:08bae8fb9824 181 * Queues an activation request. Usually only used internally.
Patrick Barrett 11:08bae8fb9824 182 *
Patrick Barrett 11:08bae8fb9824 183 */
Patrick Barrett 11:08bae8fb9824 184 void exo_activate(exo_op *op)
Patrick Barrett 11:08bae8fb9824 185 {
Patrick Barrett 11:08bae8fb9824 186 op->type = EXO_ACTIVATE;
Patrick Barrett 11:08bae8fb9824 187 op->state = EXO_REQUEST_NEW;
Patrick Barrett 11:08bae8fb9824 188 op->alias = NULL;
Patrick Barrett 11:08bae8fb9824 189 op->value = NULL;
Patrick Barrett 11:08bae8fb9824 190 op->value_max = 0;
Patrick Barrett 11:08bae8fb9824 191 op->mid = 0;
Patrick Barrett 11:08bae8fb9824 192 }
Patrick Barrett 11:08bae8fb9824 193
Patrick Barrett 0:c7393ae16c16 194 void exo_op_init(exo_op *op)
Patrick Barrett 0:c7393ae16c16 195 {
Patrick Barrett 0:c7393ae16c16 196 op->type = EXO_NULL;
Patrick Barrett 0:c7393ae16c16 197 op->state = EXO_REQUEST_NULL;
Patrick Barrett 0:c7393ae16c16 198 op->alias = NULL;
Patrick Barrett 0:c7393ae16c16 199 op->value = NULL;
Patrick Barrett 0:c7393ae16c16 200 op->value_max = 0;
Patrick Barrett 0:c7393ae16c16 201 op->mid = 0;
Patrick Barrett 10:76deeaebfafb 202 op->obs_seq = 0;
Patrick Barrett 20:e98884244926 203 op->tkl = 0;
Patrick Barrett 20:e98884244926 204 op->token = 0;
Patrick Barrett 13:df08a86dc06d 205 op->timeout = 0;
Patrick Barrett 29:004c318e63fa 206 op->retries = 0;
Patrick Barrett 0:c7393ae16c16 207 }
Patrick Barrett 0:c7393ae16c16 208
Patrick Barrett 0:c7393ae16c16 209 void exo_op_done(exo_op *op)
Patrick Barrett 0:c7393ae16c16 210 {
Patrick Barrett 0:c7393ae16c16 211 if (exo_is_op_subscribe(op)) {
Patrick Barrett 0:c7393ae16c16 212 op->state = EXO_REQUEST_SUBSCRIBED;
Patrick Barrett 0:c7393ae16c16 213 } else {
Patrick Barrett 0:c7393ae16c16 214 exo_op_init(op);
Patrick Barrett 0:c7393ae16c16 215 }
Patrick Barrett 0:c7393ae16c16 216 }
Patrick Barrett 0:c7393ae16c16 217
Patrick Barrett 0:c7393ae16c16 218 uint8_t exo_is_op_valid(exo_op *op)
Patrick Barrett 0:c7393ae16c16 219 {
Patrick Barrett 0:c7393ae16c16 220 return op->type != EXO_NULL;
Patrick Barrett 0:c7393ae16c16 221 }
Patrick Barrett 0:c7393ae16c16 222
Patrick Barrett 0:c7393ae16c16 223 uint8_t exo_is_op_success(exo_op *op)
Patrick Barrett 0:c7393ae16c16 224 {
Patrick Barrett 0:c7393ae16c16 225 return op->state == EXO_REQUEST_SUCCESS;
Patrick Barrett 0:c7393ae16c16 226 }
Patrick Barrett 0:c7393ae16c16 227
Patrick Barrett 0:c7393ae16c16 228 uint8_t exo_is_op_finished(exo_op *op)
Patrick Barrett 0:c7393ae16c16 229 {
Patrick Barrett 0:c7393ae16c16 230 return op->state == EXO_REQUEST_SUCCESS || op->state == EXO_REQUEST_ERROR;
Patrick Barrett 0:c7393ae16c16 231 }
Patrick Barrett 0:c7393ae16c16 232
Patrick Barrett 0:c7393ae16c16 233 uint8_t exo_is_op_read(exo_op *op)
Patrick Barrett 0:c7393ae16c16 234 {
Patrick Barrett 0:c7393ae16c16 235 return op->type == EXO_READ;
Patrick Barrett 0:c7393ae16c16 236 }
Patrick Barrett 0:c7393ae16c16 237
Patrick Barrett 0:c7393ae16c16 238 uint8_t exo_is_op_subscribe(exo_op *op)
Patrick Barrett 0:c7393ae16c16 239 {
Patrick Barrett 0:c7393ae16c16 240 return op->type == EXO_SUBSCRIBE;
Patrick Barrett 0:c7393ae16c16 241 }
Patrick Barrett 0:c7393ae16c16 242
Patrick Barrett 0:c7393ae16c16 243 uint8_t exo_is_op_write(exo_op *op)
Patrick Barrett 0:c7393ae16c16 244 {
Patrick Barrett 0:c7393ae16c16 245 return op->type == EXO_WRITE;
Patrick Barrett 0:c7393ae16c16 246 }
Patrick Barrett 0:c7393ae16c16 247
Patrick Barrett 0:c7393ae16c16 248
Patrick Barrett 0:c7393ae16c16 249 /*!
Patrick Barrett 0:c7393ae16c16 250 * \brief Performs queued operations with the Exosite One Platform
Patrick Barrett 0:c7393ae16c16 251 *
Patrick Barrett 0:c7393ae16c16 252 * Queues a request to read a dataport from the Exosite One Platform. If the
Patrick Barrett 0:c7393ae16c16 253 * request is successful the provided callback will be called with a single
Patrick Barrett 0:c7393ae16c16 254 * parameter, a pointer to the result as a C string.
Patrick Barrett 0:c7393ae16c16 255 *
Patrick Barrett 0:c7393ae16c16 256 * \param[in] alias Alias of dataport to read from
Patrick Barrett 0:c7393ae16c16 257 * \param[in] callback Function pointer to call on success
Patrick Barrett 0:c7393ae16c16 258 *
Patrick Barrett 0:c7393ae16c16 259 * \return EXO_STATE, EXO_OK on success or error code
Patrick Barrett 0:c7393ae16c16 260 *
Patrick Barrett 0:c7393ae16c16 261 */
Patrick Barrett 0:c7393ae16c16 262 exo_state exo_operate(exo_op *op, uint8_t count)
Patrick Barrett 0:c7393ae16c16 263 {
Patrick Barrett 12:68513d2aa2df 264 int i;
Patrick Barrett 12:68513d2aa2df 265
Patrick Barrett 12:68513d2aa2df 266 switch (device_state){
Patrick Barrett 12:68513d2aa2df 267 case EXO_STATE_UNINITIALIZED:
Patrick Barrett 12:68513d2aa2df 268 return EXO_ERROR;
Patrick Barrett 12:68513d2aa2df 269 case EXO_STATE_INITIALIZED:
Patrick Barrett 12:68513d2aa2df 270 case EXO_STATE_BAD_CIK:
Patrick Barrett 18:c463fb80d81d 271 if (op[0].state == EXO_REQUEST_NULL || op[0].timeout < exopal_get_time())
Patrick Barrett 12:68513d2aa2df 272 exo_activate(&op[0]);
Patrick Barrett 12:68513d2aa2df 273 case EXO_STATE_GOOD:
Patrick Barrett 12:68513d2aa2df 274 break;
Patrick Barrett 12:68513d2aa2df 275 }
Patrick Barrett 12:68513d2aa2df 276
Patrick Barrett 12:68513d2aa2df 277 exo_process_waiting_datagrams(op, count);
Patrick Barrett 12:68513d2aa2df 278 exo_process_active_ops(op, count);
Patrick Barrett 12:68513d2aa2df 279
Patrick Barrett 12:68513d2aa2df 280 for (i = 0; i < count; i++) {
Patrick Barrett 12:68513d2aa2df 281 if (op[i].state == EXO_REQUEST_NEW)
Patrick Barrett 12:68513d2aa2df 282 return EXO_BUSY;
Patrick Barrett 12:68513d2aa2df 283 }
Patrick Barrett 12:68513d2aa2df 284
Patrick Barrett 12:68513d2aa2df 285 for (i = 0; i < count; i++) {
Patrick Barrett 12:68513d2aa2df 286 if (op[i].state == EXO_REQUEST_PENDING)
Patrick Barrett 12:68513d2aa2df 287 return EXO_WAITING;
Patrick Barrett 12:68513d2aa2df 288 }
Patrick Barrett 12:68513d2aa2df 289
Patrick Barrett 12:68513d2aa2df 290 return EXO_IDLE;
Patrick Barrett 12:68513d2aa2df 291 }
Patrick Barrett 12:68513d2aa2df 292
Patrick Barrett 12:68513d2aa2df 293 // Internal Functions
Patrick Barrett 12:68513d2aa2df 294
Patrick Barrett 12:68513d2aa2df 295 static void exo_process_waiting_datagrams(exo_op *op, uint8_t count)
Patrick Barrett 12:68513d2aa2df 296 {
Patrick Barrett 23:e94087cd483d 297 uint8_t buf[MINIMUM_DATAGRAM_SIZE];
Patrick Barrett 0:c7393ae16c16 298 coap_pdu pdu;
Patrick Barrett 24:cfbd25fc62c4 299 coap_option opt;
Patrick Barrett 0:c7393ae16c16 300 coap_payload payload;
Patrick Barrett 0:c7393ae16c16 301 int i;
Patrick Barrett 0:c7393ae16c16 302
Patrick Barrett 0:c7393ae16c16 303 pdu.buf = buf;
Patrick Barrett 23:e94087cd483d 304 pdu.max = MINIMUM_DATAGRAM_SIZE;
Patrick Barrett 0:c7393ae16c16 305 pdu.len = 0;
Patrick Barrett 0:c7393ae16c16 306
Patrick Barrett 0:c7393ae16c16 307 // receive a UDP packet if one or more waiting
Patrick Barrett 0:c7393ae16c16 308 while (exopal_udp_recv(pdu.buf, pdu.max, &pdu.len) == 0) {
Patrick Barrett 0:c7393ae16c16 309 if (coap_validate_pkt(&pdu) != CE_NONE)
Patrick Barrett 0:c7393ae16c16 310 continue; //Invalid Packet, Ignore
Patrick Barrett 0:c7393ae16c16 311
Patrick Barrett 0:c7393ae16c16 312 for (i = 0; i < count; i++) {
Patrick Barrett 17:661d4a5b7c1b 313 if (coap_get_type(&pdu) == CT_CON || coap_get_type(&pdu) == CT_NON) {
Patrick Barrett 19:323801b9c74e 314 if (op[i].state == EXO_REQUEST_SUBSCRIBED && coap_get_token(&pdu) == op[i].token) {
Patrick Barrett 19:323801b9c74e 315 if (coap_get_code(&pdu) == CC_CONTENT) {
Patrick Barrett 19:323801b9c74e 316 uint32_t new_seq = 0;
Patrick Barrett 19:323801b9c74e 317 opt = coap_get_option_by_num(&pdu, CON_OBSERVE, 0);
Patrick Barrett 19:323801b9c74e 318 for (int j = 0; j < opt.len; j++) {
Patrick Barrett 19:323801b9c74e 319 new_seq = (new_seq << (8*j)) | opt.val[j];
Patrick Barrett 19:323801b9c74e 320 }
Patrick Barrett 13:df08a86dc06d 321
Patrick Barrett 19:323801b9c74e 322 payload = coap_get_payload(&pdu);
Patrick Barrett 19:323801b9c74e 323 if (payload.len == 0) {
Patrick Barrett 19:323801b9c74e 324 op[i].value[0] = '\0';
Patrick Barrett 19:323801b9c74e 325 } else if (payload.len+1 > op[i].value_max || op[i].value == 0) {
Patrick Barrett 19:323801b9c74e 326 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 19:323801b9c74e 327 } else{
Patrick Barrett 19:323801b9c74e 328 memcpy(op[i].value, payload.val, payload.len);
Patrick Barrett 19:323801b9c74e 329 op[i].value[payload.len] = 0;
Patrick Barrett 19:323801b9c74e 330 op[i].mid = coap_get_mid(&pdu);
Patrick Barrett 19:323801b9c74e 331 // TODO: User proper logic to ensure it's a new value not a different, but old one.
Patrick Barrett 19:323801b9c74e 332 if (op[i].obs_seq != new_seq) {
Patrick Barrett 19:323801b9c74e 333 op[i].state = EXO_REQUEST_SUB_ACK_NEW;
Patrick Barrett 19:323801b9c74e 334 op[i].obs_seq = new_seq;
Patrick Barrett 19:323801b9c74e 335 } else {
Patrick Barrett 19:323801b9c74e 336 op[i].state = EXO_REQUEST_SUB_ACK;
Patrick Barrett 19:323801b9c74e 337 }
Patrick Barrett 24:cfbd25fc62c4 338
Patrick Barrett 24:cfbd25fc62c4 339 opt = coap_get_option_by_num(&pdu, CON_MAX_AGE, 0);
Patrick Barrett 24:cfbd25fc62c4 340 uint8_t max_age = 120; // default, 2 minutes, see RFC4787 Sec 4.3
Patrick Barrett 24:cfbd25fc62c4 341 if (opt.num !=0 && opt.len == 1){ // if has Max-Age option, use it
Patrick Barrett 24:cfbd25fc62c4 342 max_age = opt.val[0];
Patrick Barrett 24:cfbd25fc62c4 343 }
Patrick Barrett 24:cfbd25fc62c4 344
Patrick Barrett 24:cfbd25fc62c4 345 // Set timeout between Max-Age to Max-Age + ACK_RANDOM_FACTOR (CoAP Defined)
Patrick Barrett 24:cfbd25fc62c4 346 op[i].timeout = exopal_get_time() + (max_age * 1000000)
Patrick Barrett 24:cfbd25fc62c4 347 + (((uint64_t)rand() % 1500000));
Patrick Barrett 19:323801b9c74e 348 }
Patrick Barrett 19:323801b9c74e 349 } else if (coap_get_code_class(&pdu) != 2) {
Patrick Barrett 13:df08a86dc06d 350 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 11:08bae8fb9824 351 }
Patrick Barrett 13:df08a86dc06d 352 break;
Patrick Barrett 0:c7393ae16c16 353 }
Patrick Barrett 17:661d4a5b7c1b 354 } else if (coap_get_type(&pdu) == CT_ACK) {
Patrick Barrett 13:df08a86dc06d 355 if (op[i].state == EXO_REQUEST_PENDING && op[i].mid == coap_get_mid(&pdu)) {
Patrick Barrett 13:df08a86dc06d 356 if (coap_get_code_class(&pdu) == 2) {
Patrick Barrett 17:661d4a5b7c1b 357 switch (op[i].type) {
Patrick Barrett 17:661d4a5b7c1b 358 case EXO_WRITE:
Patrick Barrett 17:661d4a5b7c1b 359 op[i].state = EXO_REQUEST_SUCCESS;
Patrick Barrett 17:661d4a5b7c1b 360 break;
Patrick Barrett 17:661d4a5b7c1b 361 case EXO_READ:
Patrick Barrett 17:661d4a5b7c1b 362 payload = coap_get_payload(&pdu);
Patrick Barrett 17:661d4a5b7c1b 363 if (payload.len == 0) {
Patrick Barrett 17:661d4a5b7c1b 364 op[i].value[0] = '\0';
Patrick Barrett 17:661d4a5b7c1b 365 } else if (payload.len+1 > op[i].value_max || op[i].value == 0) {
Patrick Barrett 17:661d4a5b7c1b 366 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 17:661d4a5b7c1b 367 } else{
Patrick Barrett 17:661d4a5b7c1b 368 memcpy(op[i].value, payload.val, payload.len);
Patrick Barrett 17:661d4a5b7c1b 369 op[i].value[payload.len] = 0;
Patrick Barrett 17:661d4a5b7c1b 370 op[i].state = EXO_REQUEST_SUCCESS;
Patrick Barrett 17:661d4a5b7c1b 371 }
Patrick Barrett 17:661d4a5b7c1b 372 break;
Patrick Barrett 17:661d4a5b7c1b 373 case EXO_SUBSCRIBE:
Patrick Barrett 17:661d4a5b7c1b 374 payload = coap_get_payload(&pdu);
Patrick Barrett 17:661d4a5b7c1b 375 if (payload.len == 0) {
Patrick Barrett 17:661d4a5b7c1b 376 op[i].value[0] = '\0';
Patrick Barrett 17:661d4a5b7c1b 377 } else if (payload.len+1 > op[i].value_max || op[i].value == 0) {
Patrick Barrett 17:661d4a5b7c1b 378 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 17:661d4a5b7c1b 379 } else{
Patrick Barrett 17:661d4a5b7c1b 380 memcpy(op[i].value, payload.val, payload.len);
Patrick Barrett 17:661d4a5b7c1b 381 op[i].value[payload.len] = 0;
Patrick Barrett 17:661d4a5b7c1b 382 op[i].state = EXO_REQUEST_SUCCESS;
Patrick Barrett 24:cfbd25fc62c4 383
Patrick Barrett 24:cfbd25fc62c4 384 opt = coap_get_option_by_num(&pdu, CON_MAX_AGE, 0);
Patrick Barrett 24:cfbd25fc62c4 385 uint8_t max_age = 120; // default, 2 minutes, see RFC4787 Sec 4.3
Patrick Barrett 24:cfbd25fc62c4 386 if (opt.num !=0 && opt.len == 1){ // if has Max-Age option, use it
Patrick Barrett 24:cfbd25fc62c4 387 max_age = opt.val[0];
Patrick Barrett 24:cfbd25fc62c4 388 }
Patrick Barrett 24:cfbd25fc62c4 389
Patrick Barrett 27:786cdb9c3605 390 opt = coap_get_option_by_num(&pdu, CON_OBSERVE, 0);
Patrick Barrett 27:786cdb9c3605 391 for (int j = 0; j < opt.len; j++) {
Patrick Barrett 27:786cdb9c3605 392 op[i].obs_seq = (op[i].obs_seq << (8*j)) | opt.val[j];
Patrick Barrett 27:786cdb9c3605 393 }
Patrick Barrett 27:786cdb9c3605 394
Patrick Barrett 24:cfbd25fc62c4 395 // Set timeout between Max-Age to Max-Age + ACK_RANDOM_FACTOR (CoAP Defined)
Patrick Barrett 24:cfbd25fc62c4 396 op[i].timeout = exopal_get_time() + (max_age * 1000000)
Patrick Barrett 24:cfbd25fc62c4 397 + (((uint64_t)rand() % 1500000));
Patrick Barrett 17:661d4a5b7c1b 398 }
Patrick Barrett 17:661d4a5b7c1b 399 break;
Patrick Barrett 17:661d4a5b7c1b 400 case EXO_ACTIVATE:
Patrick Barrett 17:661d4a5b7c1b 401 payload = coap_get_payload(&pdu);
Patrick Barrett 17:661d4a5b7c1b 402 if (payload.len == CIK_LENGTH) {
Patrick Barrett 17:661d4a5b7c1b 403 memcpy(cik, payload.val, CIK_LENGTH);
Patrick Barrett 17:661d4a5b7c1b 404 cik[CIK_LENGTH] = 0;
Patrick Barrett 17:661d4a5b7c1b 405 op[i].state = EXO_REQUEST_SUCCESS;
Patrick Barrett 17:661d4a5b7c1b 406 exopal_store_cik(cik);
Patrick Barrett 17:661d4a5b7c1b 407 device_state = EXO_STATE_GOOD;
Patrick Barrett 17:661d4a5b7c1b 408 } else {
Patrick Barrett 17:661d4a5b7c1b 409 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 17:661d4a5b7c1b 410 }
Patrick Barrett 17:661d4a5b7c1b 411
Patrick Barrett 17:661d4a5b7c1b 412 // We're done with this op now.
Patrick Barrett 17:661d4a5b7c1b 413 exo_op_init(&op[i]);
Patrick Barrett 17:661d4a5b7c1b 414 break;
Patrick Barrett 17:661d4a5b7c1b 415 case EXO_NULL: // pending null request? shouldn't be possible
Patrick Barrett 17:661d4a5b7c1b 416 continue;
Patrick Barrett 13:df08a86dc06d 417 }
Patrick Barrett 13:df08a86dc06d 418 } else {
Patrick Barrett 13:df08a86dc06d 419 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 17:661d4a5b7c1b 420
Patrick Barrett 17:661d4a5b7c1b 421 if (coap_get_code(&pdu) == CC_UNAUTHORIZED){
Patrick Barrett 18:c463fb80d81d 422 //device_state = EXO_STATE_BAD_CIK;
Patrick Barrett 18:c463fb80d81d 423
Patrick Barrett 18:c463fb80d81d 424 if (op[0].type == EXO_NULL || op[0].timeout < exopal_get_time())
Patrick Barrett 18:c463fb80d81d 425 exo_activate(&op[0]);
Patrick Barrett 17:661d4a5b7c1b 426 } else if (coap_get_code(&pdu) == CC_NOT_FOUND) {
Patrick Barrett 17:661d4a5b7c1b 427 device_state = EXO_STATE_GOOD;
Patrick Barrett 17:661d4a5b7c1b 428 }
Patrick Barrett 13:df08a86dc06d 429 }
Patrick Barrett 0:c7393ae16c16 430
Patrick Barrett 17:661d4a5b7c1b 431 break;
Patrick Barrett 17:661d4a5b7c1b 432 }
Patrick Barrett 17:661d4a5b7c1b 433
Patrick Barrett 17:661d4a5b7c1b 434 } else if (coap_get_type(&pdu) == CT_RST) {
Patrick Barrett 17:661d4a5b7c1b 435 if ((op[i].state == EXO_REQUEST_PENDING || op[i].state == EXO_REQUEST_SUBSCRIBED) &&
Patrick Barrett 17:661d4a5b7c1b 436 (op[i].mid == coap_get_mid(&pdu) && op[i].token == coap_get_token(&pdu))){
Patrick Barrett 17:661d4a5b7c1b 437 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 13:df08a86dc06d 438 break;
Patrick Barrett 0:c7393ae16c16 439 }
Patrick Barrett 0:c7393ae16c16 440 }
Patrick Barrett 0:c7393ae16c16 441 }
Patrick Barrett 0:c7393ae16c16 442
Patrick Barrett 13:df08a86dc06d 443 // if the above loop ends normally we don't recognize message, reply RST
Patrick Barrett 0:c7393ae16c16 444 if (i == count){
Patrick Barrett 0:c7393ae16c16 445 if (coap_get_type(&pdu) == CT_CON) {
Patrick Barrett 0:c7393ae16c16 446 // this can't fail
Patrick Barrett 0:c7393ae16c16 447 exo_build_msg_rst(&pdu, coap_get_mid(&pdu), coap_get_token(&pdu), coap_get_tkl(&pdu));
Patrick Barrett 0:c7393ae16c16 448
Patrick Barrett 0:c7393ae16c16 449 // best effort, don't bother checking if it failed, nothing we can do it
Patrick Barrett 0:c7393ae16c16 450 // it did anyway
Patrick Barrett 0:c7393ae16c16 451 exopal_udp_send(pdu.buf, pdu.len);
Patrick Barrett 0:c7393ae16c16 452 }
Patrick Barrett 0:c7393ae16c16 453
Patrick Barrett 0:c7393ae16c16 454 break;
Patrick Barrett 0:c7393ae16c16 455 }
Patrick Barrett 0:c7393ae16c16 456 }
Patrick Barrett 12:68513d2aa2df 457 }
Patrick Barrett 0:c7393ae16c16 458
Patrick Barrett 12:68513d2aa2df 459 // process all ops that are in an active state
Patrick Barrett 12:68513d2aa2df 460 static void exo_process_active_ops(exo_op *op, uint8_t count)
Patrick Barrett 12:68513d2aa2df 461 {
Patrick Barrett 23:e94087cd483d 462 uint8_t buf[MINIMUM_DATAGRAM_SIZE];
Patrick Barrett 12:68513d2aa2df 463 coap_pdu pdu;
Patrick Barrett 12:68513d2aa2df 464 int i;
Patrick Barrett 12:68513d2aa2df 465 uint64_t now = exopal_get_time();
Patrick Barrett 12:68513d2aa2df 466
Patrick Barrett 12:68513d2aa2df 467 pdu.buf = buf;
Patrick Barrett 23:e94087cd483d 468 pdu.max = MINIMUM_DATAGRAM_SIZE;
Patrick Barrett 12:68513d2aa2df 469 pdu.len = 0;
Patrick Barrett 12:68513d2aa2df 470
Patrick Barrett 0:c7393ae16c16 471 for (i = 0; i < count; i++) {
Patrick Barrett 0:c7393ae16c16 472 switch (op[i].state) {
Patrick Barrett 0:c7393ae16c16 473 case EXO_REQUEST_NEW:
Patrick Barrett 0:c7393ae16c16 474 // Build and Send Request
Patrick Barrett 0:c7393ae16c16 475 switch (op[i].type) {
Patrick Barrett 0:c7393ae16c16 476 case EXO_READ:
Patrick Barrett 0:c7393ae16c16 477 exo_build_msg_read(&pdu, op[i].alias);
Patrick Barrett 0:c7393ae16c16 478 break;
Patrick Barrett 0:c7393ae16c16 479 case EXO_SUBSCRIBE:
Patrick Barrett 0:c7393ae16c16 480 exo_build_msg_observe(&pdu, op[i].alias);
Patrick Barrett 0:c7393ae16c16 481 break;
Patrick Barrett 0:c7393ae16c16 482 case EXO_WRITE:
Patrick Barrett 0:c7393ae16c16 483 exo_build_msg_write(&pdu, op[i].alias, op[i].value);
Patrick Barrett 0:c7393ae16c16 484 break;
Patrick Barrett 11:08bae8fb9824 485 case EXO_ACTIVATE:
Patrick Barrett 11:08bae8fb9824 486 exo_build_msg_activate(&pdu, vendor, model, serial);
Patrick Barrett 11:08bae8fb9824 487 break;
Patrick Barrett 0:c7393ae16c16 488 default:
Patrick Barrett 0:c7393ae16c16 489 op[i].type = EXO_NULL;
Patrick Barrett 0:c7393ae16c16 490 continue;
Patrick Barrett 0:c7393ae16c16 491 }
Patrick Barrett 0:c7393ae16c16 492
Patrick Barrett 0:c7393ae16c16 493 if (exopal_udp_send(pdu.buf, pdu.len) == 0) {
Patrick Barrett 0:c7393ae16c16 494 op[i].state = EXO_REQUEST_PENDING;
Patrick Barrett 0:c7393ae16c16 495 op[i].timeout = exopal_get_time() + 4000000;
Patrick Barrett 0:c7393ae16c16 496 op[i].mid = coap_get_mid(&pdu);
Patrick Barrett 0:c7393ae16c16 497 op[i].token = coap_get_token(&pdu);
Patrick Barrett 0:c7393ae16c16 498 }
Patrick Barrett 0:c7393ae16c16 499
Patrick Barrett 0:c7393ae16c16 500 break;
Patrick Barrett 10:76deeaebfafb 501 case EXO_REQUEST_SUBSCRIBED:
Patrick Barrett 0:c7393ae16c16 502 case EXO_REQUEST_PENDING:
Patrick Barrett 0:c7393ae16c16 503 // check if pending requests have reached timeout
Patrick Barrett 0:c7393ae16c16 504 if (op[i].timeout <= now){
Patrick Barrett 0:c7393ae16c16 505 switch (op[i].type) {
Patrick Barrett 0:c7393ae16c16 506 case EXO_READ:
Patrick Barrett 0:c7393ae16c16 507 case EXO_WRITE:
Patrick Barrett 29:004c318e63fa 508 case EXO_ACTIVATE:
Patrick Barrett 29:004c318e63fa 509 if (op[i].retries < COAP_MAX_RETRANSMIT){
Patrick Barrett 29:004c318e63fa 510 switch (op[i].type) {
Patrick Barrett 29:004c318e63fa 511 case EXO_READ:
Patrick Barrett 29:004c318e63fa 512 exo_build_msg_read(&pdu, op[i].alias);
Patrick Barrett 29:004c318e63fa 513 break;
Patrick Barrett 29:004c318e63fa 514 case EXO_WRITE:
Patrick Barrett 29:004c318e63fa 515 exo_build_msg_write(&pdu, op[i].alias, op[i].value);
Patrick Barrett 29:004c318e63fa 516 break;
Patrick Barrett 29:004c318e63fa 517 case EXO_ACTIVATE:
Patrick Barrett 29:004c318e63fa 518 exo_build_msg_activate(&pdu, vendor, model, serial);
Patrick Barrett 29:004c318e63fa 519 break;
Patrick Barrett 29:004c318e63fa 520 default:
Patrick Barrett 29:004c318e63fa 521 break;
Patrick Barrett 29:004c318e63fa 522 }
Patrick Barrett 29:004c318e63fa 523
Patrick Barrett 29:004c318e63fa 524 // reuse old mid and token
Patrick Barrett 29:004c318e63fa 525 coap_set_mid(&pdu, op[i].mid);
Patrick Barrett 29:004c318e63fa 526 coap_set_token(&pdu, op[i].token, op[i].tkl);
Patrick Barrett 29:004c318e63fa 527
Patrick Barrett 29:004c318e63fa 528 if (exopal_udp_send(pdu.buf, pdu.len) == 0) {
Patrick Barrett 29:004c318e63fa 529 op[i].retries++;
Patrick Barrett 29:004c318e63fa 530 op[i].timeout = exopal_get_time() + (op[i].retries * COAP_PROBING_RATE * 1000000)
Patrick Barrett 29:004c318e63fa 531 + (((uint64_t)rand() % 1500000));
Patrick Barrett 29:004c318e63fa 532 }
Patrick Barrett 29:004c318e63fa 533 } else {
Patrick Barrett 29:004c318e63fa 534 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 29:004c318e63fa 535 }
Patrick Barrett 0:c7393ae16c16 536 break;
Patrick Barrett 0:c7393ae16c16 537 case EXO_SUBSCRIBE:
Patrick Barrett 0:c7393ae16c16 538 // force a new observe request
Patrick Barrett 0:c7393ae16c16 539 op[i].state = EXO_REQUEST_NEW;
Patrick Barrett 0:c7393ae16c16 540 break;
Patrick Barrett 0:c7393ae16c16 541 default:
Patrick Barrett 0:c7393ae16c16 542 break;
Patrick Barrett 0:c7393ae16c16 543 }
Patrick Barrett 0:c7393ae16c16 544 }
Patrick Barrett 0:c7393ae16c16 545 break;
Patrick Barrett 0:c7393ae16c16 546 case EXO_REQUEST_SUB_ACK_NEW:
Patrick Barrett 0:c7393ae16c16 547 case EXO_REQUEST_SUB_ACK:
Patrick Barrett 0:c7393ae16c16 548 // send ack for observe notification
Patrick Barrett 0:c7393ae16c16 549 exo_build_msg_ack(&pdu, coap_get_mid(&pdu));
Patrick Barrett 0:c7393ae16c16 550
Patrick Barrett 0:c7393ae16c16 551 if (exopal_udp_send(pdu.buf, pdu.len) == 0) {
Patrick Barrett 0:c7393ae16c16 552 if (op[i].state == EXO_REQUEST_SUB_ACK)
Patrick Barrett 0:c7393ae16c16 553 op[i].state = EXO_REQUEST_SUBSCRIBED;
Patrick Barrett 0:c7393ae16c16 554 else if (op[i].state == EXO_REQUEST_SUB_ACK_NEW)
Patrick Barrett 0:c7393ae16c16 555 op[i].state = EXO_REQUEST_SUCCESS;
Patrick Barrett 0:c7393ae16c16 556 }
Patrick Barrett 0:c7393ae16c16 557 break;
Patrick Barrett 0:c7393ae16c16 558 default:
Patrick Barrett 0:c7393ae16c16 559 break;
Patrick Barrett 0:c7393ae16c16 560 }
Patrick Barrett 0:c7393ae16c16 561 }
Patrick Barrett 0:c7393ae16c16 562 }
Patrick Barrett 0:c7393ae16c16 563
Patrick Barrett 0:c7393ae16c16 564
Patrick Barrett 0:c7393ae16c16 565 exo_error exo_build_msg_activate(coap_pdu *pdu, const char *vendor, const char *model, const char *serial_number)
Patrick Barrett 0:c7393ae16c16 566 {
Patrick Barrett 0:c7393ae16c16 567 coap_error ret;
Patrick Barrett 0:c7393ae16c16 568 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 569 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 570 ret |= coap_set_type(pdu, CT_CON);
Patrick Barrett 0:c7393ae16c16 571 ret |= coap_set_code(pdu, CC_POST);
Patrick Barrett 0:c7393ae16c16 572 ret |= coap_set_mid(pdu, message_id_counter++);
Patrick Barrett 0:c7393ae16c16 573 ret |= coap_set_token(pdu, rand(), 2);
Patrick Barrett 0:c7393ae16c16 574 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"provision", 9);
Patrick Barrett 0:c7393ae16c16 575 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"activate", 8);
Patrick Barrett 0:c7393ae16c16 576 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)vendor, strlen(vendor));
Patrick Barrett 0:c7393ae16c16 577 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)model, strlen(model));
Patrick Barrett 0:c7393ae16c16 578 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)serial_number, strlen(serial_number));
Patrick Barrett 0:c7393ae16c16 579
Patrick Barrett 0:c7393ae16c16 580 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 581 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 582
Patrick Barrett 0:c7393ae16c16 583 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 584 }
Patrick Barrett 0:c7393ae16c16 585
Patrick Barrett 0:c7393ae16c16 586 exo_error exo_build_msg_read(coap_pdu *pdu, const char *alias)
Patrick Barrett 0:c7393ae16c16 587 {
Patrick Barrett 0:c7393ae16c16 588 coap_error ret;
Patrick Barrett 0:c7393ae16c16 589 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 590 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 591 ret |= coap_set_type(pdu, CT_CON);
Patrick Barrett 0:c7393ae16c16 592 ret |= coap_set_code(pdu, CC_GET);
Patrick Barrett 0:c7393ae16c16 593 ret |= coap_set_mid(pdu, message_id_counter++);
Patrick Barrett 0:c7393ae16c16 594 ret |= coap_set_token(pdu, rand(), 2);
Patrick Barrett 0:c7393ae16c16 595 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"1a", 2);
Patrick Barrett 0:c7393ae16c16 596 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)alias, strlen(alias));
Patrick Barrett 0:c7393ae16c16 597 ret |= coap_add_option(pdu, CON_URI_QUERY, (uint8_t*)cik, 40);
Patrick Barrett 0:c7393ae16c16 598
Patrick Barrett 0:c7393ae16c16 599 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 600 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 601
Patrick Barrett 0:c7393ae16c16 602 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 603 }
Patrick Barrett 0:c7393ae16c16 604
Patrick Barrett 0:c7393ae16c16 605 exo_error exo_build_msg_observe(coap_pdu *pdu, const char *alias)
Patrick Barrett 0:c7393ae16c16 606 {
Patrick Barrett 0:c7393ae16c16 607 uint8_t obs_opt = 0;
Patrick Barrett 0:c7393ae16c16 608 coap_error ret;
Patrick Barrett 0:c7393ae16c16 609 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 610 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 611 ret |= coap_set_type(pdu, CT_CON);
Patrick Barrett 0:c7393ae16c16 612 ret |= coap_set_code(pdu, CC_GET);
Patrick Barrett 0:c7393ae16c16 613 ret |= coap_set_mid(pdu, message_id_counter++);
Patrick Barrett 0:c7393ae16c16 614 ret |= coap_set_token(pdu, rand(), 2);
Patrick Barrett 0:c7393ae16c16 615 ret |= coap_add_option(pdu, CON_OBSERVE, &obs_opt, 1);
Patrick Barrett 0:c7393ae16c16 616 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"1a", 2);
Patrick Barrett 0:c7393ae16c16 617 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)alias, strlen(alias));
Patrick Barrett 0:c7393ae16c16 618 ret |= coap_add_option(pdu, CON_URI_QUERY, (uint8_t*)cik, 40);
Patrick Barrett 0:c7393ae16c16 619
Patrick Barrett 0:c7393ae16c16 620 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 621 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 622
Patrick Barrett 0:c7393ae16c16 623 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 624 }
Patrick Barrett 0:c7393ae16c16 625
Patrick Barrett 0:c7393ae16c16 626 exo_error exo_build_msg_write(coap_pdu *pdu, const char *alias, const char *value)
Patrick Barrett 0:c7393ae16c16 627 {
Patrick Barrett 0:c7393ae16c16 628 coap_error ret;
Patrick Barrett 0:c7393ae16c16 629 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 630 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 631 ret |= coap_set_type(pdu, CT_CON);
Patrick Barrett 0:c7393ae16c16 632 ret |= coap_set_code(pdu, CC_POST);
Patrick Barrett 0:c7393ae16c16 633 ret |= coap_set_mid(pdu, message_id_counter++);
Patrick Barrett 0:c7393ae16c16 634 ret |= coap_set_token(pdu, rand(), 2);
Patrick Barrett 0:c7393ae16c16 635 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"1a", 2);
Patrick Barrett 0:c7393ae16c16 636 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)alias, strlen(alias));
Patrick Barrett 0:c7393ae16c16 637 ret |= coap_add_option(pdu, CON_URI_QUERY, (uint8_t*)cik, 40);
Patrick Barrett 0:c7393ae16c16 638 ret |= coap_set_payload(pdu, (uint8_t *)value, strlen(value));
Patrick Barrett 0:c7393ae16c16 639
Patrick Barrett 0:c7393ae16c16 640 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 641 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 642
Patrick Barrett 0:c7393ae16c16 643 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 644 }
Patrick Barrett 0:c7393ae16c16 645
Patrick Barrett 0:c7393ae16c16 646 exo_error exo_build_msg_rst(coap_pdu *pdu, const uint16_t mid, const uint64_t token, const uint8_t tkl)
Patrick Barrett 0:c7393ae16c16 647 {
Patrick Barrett 0:c7393ae16c16 648 coap_error ret;
Patrick Barrett 0:c7393ae16c16 649 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 650 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 651 ret |= coap_set_type(pdu, CT_RST);
Patrick Barrett 0:c7393ae16c16 652 ret |= coap_set_code(pdu, CC_EMPTY);
Patrick Barrett 0:c7393ae16c16 653 ret |= coap_set_mid(pdu, mid);
Patrick Barrett 0:c7393ae16c16 654 ret |= coap_set_token(pdu, token, tkl);
Patrick Barrett 0:c7393ae16c16 655
Patrick Barrett 0:c7393ae16c16 656 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 657 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 658
Patrick Barrett 0:c7393ae16c16 659 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 660 }
Patrick Barrett 0:c7393ae16c16 661
Patrick Barrett 0:c7393ae16c16 662 exo_error exo_build_msg_ack(coap_pdu *pdu, const uint16_t mid)
Patrick Barrett 0:c7393ae16c16 663 {
Patrick Barrett 0:c7393ae16c16 664 coap_error ret;
Patrick Barrett 0:c7393ae16c16 665 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 666 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 667 ret |= coap_set_type(pdu, CT_ACK);
Patrick Barrett 0:c7393ae16c16 668 ret |= coap_set_code(pdu, CC_EMPTY);
Patrick Barrett 0:c7393ae16c16 669 ret |= coap_set_mid(pdu, mid);
Patrick Barrett 0:c7393ae16c16 670
Patrick Barrett 0:c7393ae16c16 671 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 672 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 673
Patrick Barrett 0:c7393ae16c16 674 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 675 }
Patrick Barrett 0:c7393ae16c16 676
Patrick Barrett 11:08bae8fb9824 677 exo_error exo_do_activate()
Patrick Barrett 0:c7393ae16c16 678 {
Patrick Barrett 11:08bae8fb9824 679 exo_op op;
Patrick Barrett 11:08bae8fb9824 680
Patrick Barrett 11:08bae8fb9824 681 exo_op_init(&op);
Patrick Barrett 11:08bae8fb9824 682
Patrick Barrett 0:c7393ae16c16 683
Patrick Barrett 11:08bae8fb9824 684 return EXO_OK;
Patrick Barrett 11:08bae8fb9824 685 }
Patrick Barrett 11:08bae8fb9824 686
Patrick Barrett 11:08bae8fb9824 687 uint8_t exo_util_is_ascii_hex(const char *str, size_t len)
Patrick Barrett 11:08bae8fb9824 688 {
Patrick Barrett 11:08bae8fb9824 689 size_t i;
Patrick Barrett 11:08bae8fb9824 690
Patrick Barrett 11:08bae8fb9824 691 for (i = 0; i < len; i++) {
Patrick Barrett 11:08bae8fb9824 692 if (!((str[i] >= 'a' && str[i] <= 'f') ||
Patrick Barrett 11:08bae8fb9824 693 (str[i] >= '0' && str[i] <= '9'))) {
Patrick Barrett 0:c7393ae16c16 694 return 1;
Patrick Barrett 0:c7393ae16c16 695 }
Patrick Barrett 0:c7393ae16c16 696 }
Patrick Barrett 0:c7393ae16c16 697
Patrick Barrett 0:c7393ae16c16 698 return 0;
Patrick Barrett 0:c7393ae16c16 699 }
Patrick Barrett 0:c7393ae16c16 700