Patrick Barrett / libexositecoap
Committer:
Patrick Barrett
Date:
Thu Dec 18 16:00:10 2014 -0600
Revision:
0:c7393ae16c16
Child:
10:76deeaebfafb
initial commit; working example on POSIX

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 0:c7393ae16c16 46 exo_error exo_build_msg_activate(coap_pdu *pdu, const char *vendor, const char *model, const char *serial_number);
Patrick Barrett 0:c7393ae16c16 47 exo_error exo_build_msg_read(coap_pdu *pdu, const char *alias);
Patrick Barrett 0:c7393ae16c16 48 exo_error exo_build_msg_observe(coap_pdu *pdu, const char *alias);
Patrick Barrett 0:c7393ae16c16 49 exo_error exo_build_msg_write(coap_pdu *pdu, const char *alias, const char *value);
Patrick Barrett 0:c7393ae16c16 50 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 51 exo_error exo_build_msg_ack(coap_pdu *pdu, const uint16_t mid);
Patrick Barrett 0:c7393ae16c16 52 uint8_t exosite_validate_cik(char *cik);
Patrick Barrett 0:c7393ae16c16 53
Patrick Barrett 0:c7393ae16c16 54 // Local Variables
Patrick Barrett 0:c7393ae16c16 55 static char cik[CIK_LENGTH + 1];
Patrick Barrett 0:c7393ae16c16 56 static const char *vendor;
Patrick Barrett 0:c7393ae16c16 57 static const char *model;
Patrick Barrett 0:c7393ae16c16 58 static const char *serial;
Patrick Barrett 0:c7393ae16c16 59 static uint16_t message_id_counter;
Patrick Barrett 0:c7393ae16c16 60 static exo_device_state device_state = EXO_STATE_UNINITIALIZED;
Patrick Barrett 0:c7393ae16c16 61
Patrick Barrett 0:c7393ae16c16 62 /*!
Patrick Barrett 0:c7393ae16c16 63 * \brief Initializes the Exosite library
Patrick Barrett 0:c7393ae16c16 64 *
Patrick Barrett 0:c7393ae16c16 65 * This **MUST** be called before any other exosite library calls are called.
Patrick Barrett 0:c7393ae16c16 66 *
Patrick Barrett 0:c7393ae16c16 67 * \param[in] *vendor Pointer to string containing the vendor name
Patrick Barrett 0:c7393ae16c16 68 * \param[in] *model Pointer to string containing the model name
Patrick Barrett 0:c7393ae16c16 69 * \param[in] *serial Pointer to string containing the serial number
Patrick Barrett 0:c7393ae16c16 70 *
Patrick Barrett 0:c7393ae16c16 71 * \return EXO_ERROR, EXO_OK on success, else error code
Patrick Barrett 0:c7393ae16c16 72 */
Patrick Barrett 0:c7393ae16c16 73 exo_error exo_init(const char *vendor_in, const char *model_in, const char *serial_in)
Patrick Barrett 0:c7393ae16c16 74 {
Patrick Barrett 0:c7393ae16c16 75 device_state = EXO_STATE_UNINITIALIZED;
Patrick Barrett 0:c7393ae16c16 76
Patrick Barrett 0:c7393ae16c16 77 if (exopal_init() != 0) {
Patrick Barrett 0:c7393ae16c16 78 return EXO_FATAL_ERROR_PAL;
Patrick Barrett 0:c7393ae16c16 79 }
Patrick Barrett 0:c7393ae16c16 80
Patrick Barrett 0:c7393ae16c16 81 srand(time(NULL));
Patrick Barrett 0:c7393ae16c16 82 message_id_counter = rand();
Patrick Barrett 0:c7393ae16c16 83
Patrick Barrett 0:c7393ae16c16 84 serial = serial_in;
Patrick Barrett 0:c7393ae16c16 85 vendor = vendor_in;
Patrick Barrett 0:c7393ae16c16 86 model = model_in;
Patrick Barrett 0:c7393ae16c16 87
Patrick Barrett 0:c7393ae16c16 88 if (exopal_retrieve_cik(cik) > 1){
Patrick Barrett 0:c7393ae16c16 89 return EXO_FATAL_ERROR_PAL;
Patrick Barrett 0:c7393ae16c16 90 } else {
Patrick Barrett 0:c7393ae16c16 91 cik[40] = 0;
Patrick Barrett 0:c7393ae16c16 92 }
Patrick Barrett 0:c7393ae16c16 93
Patrick Barrett 0:c7393ae16c16 94 if (exopal_udp_sock() != 0) {
Patrick Barrett 0:c7393ae16c16 95 return EXO_FATAL_ERROR_PAL;
Patrick Barrett 0:c7393ae16c16 96 }
Patrick Barrett 0:c7393ae16c16 97
Patrick Barrett 0:c7393ae16c16 98 device_state = EXO_STATE_INITIALIZED;
Patrick Barrett 0:c7393ae16c16 99
Patrick Barrett 0:c7393ae16c16 100 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 101 }
Patrick Barrett 0:c7393ae16c16 102
Patrick Barrett 0:c7393ae16c16 103 /*!
Patrick Barrett 0:c7393ae16c16 104 * \brief Queues a Write to the Exosite One Platform
Patrick Barrett 0:c7393ae16c16 105 *
Patrick Barrett 0:c7393ae16c16 106 * Queues a request to write to a dataport.
Patrick Barrett 0:c7393ae16c16 107 *
Patrick Barrett 0:c7393ae16c16 108 * \param[in] *alias Alias of dataport to write to, pointer must remain
Patrick Barrett 0:c7393ae16c16 109 * valid until the request has been sent.
Patrick Barrett 0:c7393ae16c16 110 * \param[in] callback Function pointer to call on success
Patrick Barrett 0:c7393ae16c16 111 *
Patrick Barrett 0:c7393ae16c16 112 * \return EXO_ERROR, EXO_OK on success or error code
Patrick Barrett 0:c7393ae16c16 113 *
Patrick Barrett 0:c7393ae16c16 114 */
Patrick Barrett 0:c7393ae16c16 115
Patrick Barrett 0:c7393ae16c16 116 void exo_write(exo_op *op, const char * alias, const char * value)
Patrick Barrett 0:c7393ae16c16 117 {
Patrick Barrett 0:c7393ae16c16 118 op->type = EXO_WRITE;
Patrick Barrett 0:c7393ae16c16 119 op->state = EXO_REQUEST_NEW;
Patrick Barrett 0:c7393ae16c16 120 op->alias = alias;
Patrick Barrett 0:c7393ae16c16 121 op->value = (char *)value; // this is kinda dirty, I know
Patrick Barrett 0:c7393ae16c16 122 op->value_max = 0;
Patrick Barrett 0:c7393ae16c16 123 op->mid = 0;
Patrick Barrett 0:c7393ae16c16 124 }
Patrick Barrett 0:c7393ae16c16 125
Patrick Barrett 0:c7393ae16c16 126 /*!
Patrick Barrett 0:c7393ae16c16 127 * \brief Queues a Read from the Exosite One Platform
Patrick Barrett 0:c7393ae16c16 128 *
Patrick Barrett 0:c7393ae16c16 129 * Queues a request to read a dataport. If the request is successful, the
Patrick Barrett 0:c7393ae16c16 130 * provided callback will be called with a single parameter, a pointer to the
Patrick Barrett 0:c7393ae16c16 131 * result as a C string.
Patrick Barrett 0:c7393ae16c16 132 *
Patrick Barrett 0:c7393ae16c16 133 * \param[in] *alias Alias of dataport to read from, pointer must remain
Patrick Barrett 0:c7393ae16c16 134 * valid until the request has been sent.
Patrick Barrett 0:c7393ae16c16 135 * \param[in] callback Function pointer to call on success
Patrick Barrett 0:c7393ae16c16 136 *
Patrick Barrett 0:c7393ae16c16 137 * \return EXO_ERROR, EXO_OK on success or error code
Patrick Barrett 0:c7393ae16c16 138 *
Patrick Barrett 0:c7393ae16c16 139 */
Patrick Barrett 0:c7393ae16c16 140 void exo_read(exo_op *op, const char * alias, char * value, const size_t value_max)
Patrick Barrett 0:c7393ae16c16 141 {
Patrick Barrett 0:c7393ae16c16 142 op->type = EXO_READ;
Patrick Barrett 0:c7393ae16c16 143 op->state = EXO_REQUEST_NEW;
Patrick Barrett 0:c7393ae16c16 144 op->alias = alias;
Patrick Barrett 0:c7393ae16c16 145 op->value = value;
Patrick Barrett 0:c7393ae16c16 146 op->value_max = value_max;
Patrick Barrett 0:c7393ae16c16 147 op->mid = 0;
Patrick Barrett 0:c7393ae16c16 148 }
Patrick Barrett 0:c7393ae16c16 149
Patrick Barrett 0:c7393ae16c16 150 /*!
Patrick Barrett 0:c7393ae16c16 151 * \brief Subscribes to a Dataport on the Exosite One Platform
Patrick Barrett 0:c7393ae16c16 152 *
Patrick Barrett 0:c7393ae16c16 153 * Begins a subscription to a dataport The callback is called any time the
Patrick Barrett 0:c7393ae16c16 154 * value is updated as well as when the subscription is started.
Patrick Barrett 0:c7393ae16c16 155 *
Patrick Barrett 0:c7393ae16c16 156 * \param[in] alias Alias of dataport to read from
Patrick Barrett 0:c7393ae16c16 157 * \param[in] callback Function pointer to call on change
Patrick Barrett 0:c7393ae16c16 158 *
Patrick Barrett 0:c7393ae16c16 159 * \return EXO_ERROR, EXO_OK on success or error code
Patrick Barrett 0:c7393ae16c16 160 *
Patrick Barrett 0:c7393ae16c16 161 */
Patrick Barrett 0:c7393ae16c16 162 void exo_subscribe(exo_op *op, const char * alias, char * value, const size_t value_max)
Patrick Barrett 0:c7393ae16c16 163 {
Patrick Barrett 0:c7393ae16c16 164 op->type = EXO_SUBSCRIBE;
Patrick Barrett 0:c7393ae16c16 165 op->state = EXO_REQUEST_NEW;
Patrick Barrett 0:c7393ae16c16 166 op->alias = alias;
Patrick Barrett 0:c7393ae16c16 167 op->value = value;
Patrick Barrett 0:c7393ae16c16 168 op->value_max = value_max;
Patrick Barrett 0:c7393ae16c16 169 op->mid = 0;
Patrick Barrett 0:c7393ae16c16 170 }
Patrick Barrett 0:c7393ae16c16 171
Patrick Barrett 0:c7393ae16c16 172 void exo_op_init(exo_op *op)
Patrick Barrett 0:c7393ae16c16 173 {
Patrick Barrett 0:c7393ae16c16 174 op->type = EXO_NULL;
Patrick Barrett 0:c7393ae16c16 175 op->state = EXO_REQUEST_NULL;
Patrick Barrett 0:c7393ae16c16 176 op->alias = NULL;
Patrick Barrett 0:c7393ae16c16 177 op->value = NULL;
Patrick Barrett 0:c7393ae16c16 178 op->value_max = 0;
Patrick Barrett 0:c7393ae16c16 179 op->mid = 0;
Patrick Barrett 0:c7393ae16c16 180 }
Patrick Barrett 0:c7393ae16c16 181
Patrick Barrett 0:c7393ae16c16 182 void exo_op_done(exo_op *op)
Patrick Barrett 0:c7393ae16c16 183 {
Patrick Barrett 0:c7393ae16c16 184 if (exo_is_op_subscribe(op)) {
Patrick Barrett 0:c7393ae16c16 185 op->state = EXO_REQUEST_SUBSCRIBED;
Patrick Barrett 0:c7393ae16c16 186 } else {
Patrick Barrett 0:c7393ae16c16 187 exo_op_init(op);
Patrick Barrett 0:c7393ae16c16 188 }
Patrick Barrett 0:c7393ae16c16 189 }
Patrick Barrett 0:c7393ae16c16 190
Patrick Barrett 0:c7393ae16c16 191 uint8_t exo_is_op_valid(exo_op *op)
Patrick Barrett 0:c7393ae16c16 192 {
Patrick Barrett 0:c7393ae16c16 193 return op->type != EXO_NULL;
Patrick Barrett 0:c7393ae16c16 194 }
Patrick Barrett 0:c7393ae16c16 195
Patrick Barrett 0:c7393ae16c16 196 uint8_t exo_is_op_success(exo_op *op)
Patrick Barrett 0:c7393ae16c16 197 {
Patrick Barrett 0:c7393ae16c16 198 return op->state == EXO_REQUEST_SUCCESS;
Patrick Barrett 0:c7393ae16c16 199 }
Patrick Barrett 0:c7393ae16c16 200
Patrick Barrett 0:c7393ae16c16 201 uint8_t exo_is_op_finished(exo_op *op)
Patrick Barrett 0:c7393ae16c16 202 {
Patrick Barrett 0:c7393ae16c16 203 return op->state == EXO_REQUEST_SUCCESS || op->state == EXO_REQUEST_ERROR;
Patrick Barrett 0:c7393ae16c16 204 }
Patrick Barrett 0:c7393ae16c16 205
Patrick Barrett 0:c7393ae16c16 206 uint8_t exo_is_op_read(exo_op *op)
Patrick Barrett 0:c7393ae16c16 207 {
Patrick Barrett 0:c7393ae16c16 208 return op->type == EXO_READ;
Patrick Barrett 0:c7393ae16c16 209 }
Patrick Barrett 0:c7393ae16c16 210
Patrick Barrett 0:c7393ae16c16 211 uint8_t exo_is_op_subscribe(exo_op *op)
Patrick Barrett 0:c7393ae16c16 212 {
Patrick Barrett 0:c7393ae16c16 213 return op->type == EXO_SUBSCRIBE;
Patrick Barrett 0:c7393ae16c16 214 }
Patrick Barrett 0:c7393ae16c16 215
Patrick Barrett 0:c7393ae16c16 216 uint8_t exo_is_op_write(exo_op *op)
Patrick Barrett 0:c7393ae16c16 217 {
Patrick Barrett 0:c7393ae16c16 218 return op->type == EXO_WRITE;
Patrick Barrett 0:c7393ae16c16 219 }
Patrick Barrett 0:c7393ae16c16 220
Patrick Barrett 0:c7393ae16c16 221
Patrick Barrett 0:c7393ae16c16 222 /*!
Patrick Barrett 0:c7393ae16c16 223 * \brief Performs queued operations with the Exosite One Platform
Patrick Barrett 0:c7393ae16c16 224 *
Patrick Barrett 0:c7393ae16c16 225 * Queues a request to read a dataport from the Exosite One Platform. If the
Patrick Barrett 0:c7393ae16c16 226 * request is successful the provided callback will be called with a single
Patrick Barrett 0:c7393ae16c16 227 * parameter, a pointer to the result as a C string.
Patrick Barrett 0:c7393ae16c16 228 *
Patrick Barrett 0:c7393ae16c16 229 * \param[in] alias Alias of dataport to read from
Patrick Barrett 0:c7393ae16c16 230 * \param[in] callback Function pointer to call on success
Patrick Barrett 0:c7393ae16c16 231 *
Patrick Barrett 0:c7393ae16c16 232 * \return EXO_STATE, EXO_OK on success or error code
Patrick Barrett 0:c7393ae16c16 233 *
Patrick Barrett 0:c7393ae16c16 234 */
Patrick Barrett 0:c7393ae16c16 235 exo_state exo_operate(exo_op *op, uint8_t count)
Patrick Barrett 0:c7393ae16c16 236 {
Patrick Barrett 0:c7393ae16c16 237 uint8_t buf[576];
Patrick Barrett 0:c7393ae16c16 238 coap_pdu pdu;
Patrick Barrett 0:c7393ae16c16 239 coap_payload payload;
Patrick Barrett 0:c7393ae16c16 240 int i;
Patrick Barrett 0:c7393ae16c16 241 uint64_t now = exopal_get_time();
Patrick Barrett 0:c7393ae16c16 242
Patrick Barrett 0:c7393ae16c16 243 pdu.buf = buf;
Patrick Barrett 0:c7393ae16c16 244 pdu.max = 576;
Patrick Barrett 0:c7393ae16c16 245 pdu.len = 0;
Patrick Barrett 0:c7393ae16c16 246
Patrick Barrett 0:c7393ae16c16 247 // receive a UDP packet if one or more waiting
Patrick Barrett 0:c7393ae16c16 248 while (exopal_udp_recv(pdu.buf, pdu.max, &pdu.len) == 0) {
Patrick Barrett 0:c7393ae16c16 249 if (coap_validate_pkt(&pdu) != CE_NONE)
Patrick Barrett 0:c7393ae16c16 250 continue; //Invalid Packet, Ignore
Patrick Barrett 0:c7393ae16c16 251
Patrick Barrett 0:c7393ae16c16 252 for (i = 0; i < count; i++) {
Patrick Barrett 0:c7393ae16c16 253 if (op[i].state == EXO_REQUEST_PENDING && op[i].mid == coap_get_mid(&pdu)) {
Patrick Barrett 0:c7393ae16c16 254 //have a reply to a message, process
Patrick Barrett 0:c7393ae16c16 255 if (coap_get_code_class(&pdu) == 2) {
Patrick Barrett 0:c7393ae16c16 256 payload = coap_get_payload(&pdu);
Patrick Barrett 0:c7393ae16c16 257 switch(op[i].type){
Patrick Barrett 0:c7393ae16c16 258 case EXO_READ:
Patrick Barrett 0:c7393ae16c16 259 if (payload.len == 0) {
Patrick Barrett 0:c7393ae16c16 260 op[i].value = 0;
Patrick Barrett 0:c7393ae16c16 261 } else if (payload.len+1 > op[i].value_max || op[i].value == 0) {
Patrick Barrett 0:c7393ae16c16 262 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 0:c7393ae16c16 263 } else{
Patrick Barrett 0:c7393ae16c16 264 memcpy(op[i].value, payload.val, payload.len);
Patrick Barrett 0:c7393ae16c16 265 op[i].value[payload.len] = 0;
Patrick Barrett 0:c7393ae16c16 266 op[i].state = EXO_REQUEST_SUCCESS;
Patrick Barrett 0:c7393ae16c16 267 }
Patrick Barrett 0:c7393ae16c16 268 break;
Patrick Barrett 0:c7393ae16c16 269 case EXO_SUBSCRIBE:
Patrick Barrett 0:c7393ae16c16 270 if (payload.len == 0) {
Patrick Barrett 0:c7393ae16c16 271 op[i].value = 0;
Patrick Barrett 0:c7393ae16c16 272 } else if (payload.len+1 > op[i].value_max || op[i].value == 0) {
Patrick Barrett 0:c7393ae16c16 273 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 0:c7393ae16c16 274 } else{
Patrick Barrett 0:c7393ae16c16 275 memcpy(op[i].value, payload.val, payload.len);
Patrick Barrett 0:c7393ae16c16 276 op[i].value[payload.len] = 0;
Patrick Barrett 0:c7393ae16c16 277 op[i].state = EXO_REQUEST_SUCCESS;
Patrick Barrett 0:c7393ae16c16 278 }
Patrick Barrett 0:c7393ae16c16 279 break;
Patrick Barrett 0:c7393ae16c16 280 case EXO_WRITE:
Patrick Barrett 0:c7393ae16c16 281 op[i].state = EXO_REQUEST_SUCCESS;
Patrick Barrett 0:c7393ae16c16 282 break;
Patrick Barrett 0:c7393ae16c16 283 default:
Patrick Barrett 0:c7393ae16c16 284 break;
Patrick Barrett 0:c7393ae16c16 285 }
Patrick Barrett 0:c7393ae16c16 286 } else {
Patrick Barrett 0:c7393ae16c16 287 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 0:c7393ae16c16 288 }
Patrick Barrett 0:c7393ae16c16 289 break;
Patrick Barrett 0:c7393ae16c16 290 }else if (op[i].state == EXO_REQUEST_SUBSCRIBED && coap_get_token(&pdu) == op[i].token) {
Patrick Barrett 0:c7393ae16c16 291
Patrick Barrett 0:c7393ae16c16 292 coap_option opt;
Patrick Barrett 0:c7393ae16c16 293 uint32_t new_seq = 0;
Patrick Barrett 0:c7393ae16c16 294 opt = coap_get_option_by_num(&pdu, CON_OBSERVE, 0);
Patrick Barrett 0:c7393ae16c16 295 for (int j = 0; j < opt.len; j++) {
Patrick Barrett 0:c7393ae16c16 296 new_seq = (new_seq << (8*j)) | opt.val[j];
Patrick Barrett 0:c7393ae16c16 297 }
Patrick Barrett 0:c7393ae16c16 298
Patrick Barrett 0:c7393ae16c16 299 payload = coap_get_payload(&pdu);
Patrick Barrett 0:c7393ae16c16 300 if (payload.len == 0) {
Patrick Barrett 0:c7393ae16c16 301 op[i].value = 0;
Patrick Barrett 0:c7393ae16c16 302 } else if (payload.len+1 > op[i].value_max || op[i].value == 0) {
Patrick Barrett 0:c7393ae16c16 303 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 0:c7393ae16c16 304 } else{
Patrick Barrett 0:c7393ae16c16 305 memcpy(op[i].value, payload.val, payload.len);
Patrick Barrett 0:c7393ae16c16 306 op[i].value[payload.len] = 0;
Patrick Barrett 0:c7393ae16c16 307 op[i].mid = coap_get_mid(&pdu);
Patrick Barrett 0:c7393ae16c16 308 // TODO: User proper logic to ensure it's a new value not a different, but old one.
Patrick Barrett 0:c7393ae16c16 309 if (op[i].obs_seq != new_seq) {
Patrick Barrett 0:c7393ae16c16 310 op[i].state = EXO_REQUEST_SUB_ACK_NEW;
Patrick Barrett 0:c7393ae16c16 311 op[i].obs_seq = new_seq;
Patrick Barrett 0:c7393ae16c16 312 } else {
Patrick Barrett 0:c7393ae16c16 313 op[i].state = EXO_REQUEST_SUB_ACK;
Patrick Barrett 0:c7393ae16c16 314 }
Patrick Barrett 0:c7393ae16c16 315 }
Patrick Barrett 0:c7393ae16c16 316 break;
Patrick Barrett 0:c7393ae16c16 317 }
Patrick Barrett 0:c7393ae16c16 318 }
Patrick Barrett 0:c7393ae16c16 319
Patrick Barrett 0:c7393ae16c16 320 if (i == count){
Patrick Barrett 0:c7393ae16c16 321 if (coap_get_type(&pdu) == CT_CON) {
Patrick Barrett 0:c7393ae16c16 322 // this can't fail
Patrick Barrett 0:c7393ae16c16 323 exo_build_msg_rst(&pdu, coap_get_mid(&pdu), coap_get_token(&pdu), coap_get_tkl(&pdu));
Patrick Barrett 0:c7393ae16c16 324
Patrick Barrett 0:c7393ae16c16 325 // best effort, don't bother checking if it failed, nothing we can do it
Patrick Barrett 0:c7393ae16c16 326 // it did anyway
Patrick Barrett 0:c7393ae16c16 327 exopal_udp_send(pdu.buf, pdu.len);
Patrick Barrett 0:c7393ae16c16 328 }
Patrick Barrett 0:c7393ae16c16 329
Patrick Barrett 0:c7393ae16c16 330 break;
Patrick Barrett 0:c7393ae16c16 331 }
Patrick Barrett 0:c7393ae16c16 332 }
Patrick Barrett 0:c7393ae16c16 333
Patrick Barrett 0:c7393ae16c16 334 // process all requests that need something done
Patrick Barrett 0:c7393ae16c16 335 for (i = 0; i < count; i++) {
Patrick Barrett 0:c7393ae16c16 336 switch (op[i].state) {
Patrick Barrett 0:c7393ae16c16 337 case EXO_REQUEST_NEW:
Patrick Barrett 0:c7393ae16c16 338 // Build and Send Request
Patrick Barrett 0:c7393ae16c16 339 switch (op[i].type) {
Patrick Barrett 0:c7393ae16c16 340 case EXO_READ:
Patrick Barrett 0:c7393ae16c16 341 exo_build_msg_read(&pdu, op[i].alias);
Patrick Barrett 0:c7393ae16c16 342 break;
Patrick Barrett 0:c7393ae16c16 343 case EXO_SUBSCRIBE:
Patrick Barrett 0:c7393ae16c16 344 exo_build_msg_observe(&pdu, op[i].alias);
Patrick Barrett 0:c7393ae16c16 345 break;
Patrick Barrett 0:c7393ae16c16 346 case EXO_WRITE:
Patrick Barrett 0:c7393ae16c16 347 exo_build_msg_write(&pdu, op[i].alias, op[i].value);
Patrick Barrett 0:c7393ae16c16 348 break;
Patrick Barrett 0:c7393ae16c16 349 default:
Patrick Barrett 0:c7393ae16c16 350 op[i].type = EXO_NULL;
Patrick Barrett 0:c7393ae16c16 351 continue;
Patrick Barrett 0:c7393ae16c16 352 }
Patrick Barrett 0:c7393ae16c16 353
Patrick Barrett 0:c7393ae16c16 354 if (exopal_udp_send(pdu.buf, pdu.len) == 0) {
Patrick Barrett 0:c7393ae16c16 355 op[i].state = EXO_REQUEST_PENDING;
Patrick Barrett 0:c7393ae16c16 356 op[i].timeout = exopal_get_time() + 4000000;
Patrick Barrett 0:c7393ae16c16 357 op[i].mid = coap_get_mid(&pdu);
Patrick Barrett 0:c7393ae16c16 358 op[i].token = coap_get_token(&pdu);
Patrick Barrett 0:c7393ae16c16 359 }
Patrick Barrett 0:c7393ae16c16 360
Patrick Barrett 0:c7393ae16c16 361 break;
Patrick Barrett 0:c7393ae16c16 362 case EXO_REQUEST_PENDING:
Patrick Barrett 0:c7393ae16c16 363 // check if pending requests have reached timeout
Patrick Barrett 0:c7393ae16c16 364 if (op[i].timeout <= now){
Patrick Barrett 0:c7393ae16c16 365 switch (op[i].type) {
Patrick Barrett 0:c7393ae16c16 366 case EXO_READ:
Patrick Barrett 0:c7393ae16c16 367 case EXO_WRITE:
Patrick Barrett 0:c7393ae16c16 368 // TODO: may want to do some sort of retry system
Patrick Barrett 0:c7393ae16c16 369 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 0:c7393ae16c16 370 break;
Patrick Barrett 0:c7393ae16c16 371 case EXO_SUBSCRIBE:
Patrick Barrett 0:c7393ae16c16 372 // force a new observe request
Patrick Barrett 0:c7393ae16c16 373 op[i].state = EXO_REQUEST_NEW;
Patrick Barrett 0:c7393ae16c16 374 break;
Patrick Barrett 0:c7393ae16c16 375 default:
Patrick Barrett 0:c7393ae16c16 376 break;
Patrick Barrett 0:c7393ae16c16 377 }
Patrick Barrett 0:c7393ae16c16 378 }
Patrick Barrett 0:c7393ae16c16 379 break;
Patrick Barrett 0:c7393ae16c16 380 case EXO_REQUEST_SUB_ACK_NEW:
Patrick Barrett 0:c7393ae16c16 381 case EXO_REQUEST_SUB_ACK:
Patrick Barrett 0:c7393ae16c16 382 // send ack for observe notification
Patrick Barrett 0:c7393ae16c16 383 exo_build_msg_ack(&pdu, coap_get_mid(&pdu));
Patrick Barrett 0:c7393ae16c16 384
Patrick Barrett 0:c7393ae16c16 385 if (exopal_udp_send(pdu.buf, pdu.len) == 0) {
Patrick Barrett 0:c7393ae16c16 386 if (op[i].state == EXO_REQUEST_SUB_ACK)
Patrick Barrett 0:c7393ae16c16 387 op[i].state = EXO_REQUEST_SUBSCRIBED;
Patrick Barrett 0:c7393ae16c16 388 else if (op[i].state == EXO_REQUEST_SUB_ACK_NEW)
Patrick Barrett 0:c7393ae16c16 389 op[i].state = EXO_REQUEST_SUCCESS;
Patrick Barrett 0:c7393ae16c16 390
Patrick Barrett 0:c7393ae16c16 391 // TODO: this should get set to Max-Age value, hard coding 120 s
Patrick Barrett 0:c7393ae16c16 392 op[i].timeout = exopal_get_time() + 120000000 + (rand() % 15);
Patrick Barrett 0:c7393ae16c16 393 }
Patrick Barrett 0:c7393ae16c16 394 break;
Patrick Barrett 0:c7393ae16c16 395 default:
Patrick Barrett 0:c7393ae16c16 396 break;
Patrick Barrett 0:c7393ae16c16 397 }
Patrick Barrett 0:c7393ae16c16 398 }
Patrick Barrett 0:c7393ae16c16 399
Patrick Barrett 0:c7393ae16c16 400 for (i = 0; i < count; i++) {
Patrick Barrett 0:c7393ae16c16 401 if (op[i].state == EXO_REQUEST_NEW)
Patrick Barrett 0:c7393ae16c16 402 return EXO_BUSY;
Patrick Barrett 0:c7393ae16c16 403 }
Patrick Barrett 0:c7393ae16c16 404
Patrick Barrett 0:c7393ae16c16 405 for (i = 0; i < count; i++) {
Patrick Barrett 0:c7393ae16c16 406 if (op[i].state == EXO_REQUEST_PENDING)
Patrick Barrett 0:c7393ae16c16 407 return EXO_WAITING;
Patrick Barrett 0:c7393ae16c16 408 }
Patrick Barrett 0:c7393ae16c16 409
Patrick Barrett 0:c7393ae16c16 410 return EXO_IDLE;
Patrick Barrett 0:c7393ae16c16 411 }
Patrick Barrett 0:c7393ae16c16 412
Patrick Barrett 0:c7393ae16c16 413 // Internal Functions
Patrick Barrett 0:c7393ae16c16 414
Patrick Barrett 0:c7393ae16c16 415 exo_error exo_build_msg_activate(coap_pdu *pdu, const char *vendor, const char *model, const char *serial_number)
Patrick Barrett 0:c7393ae16c16 416 {
Patrick Barrett 0:c7393ae16c16 417 coap_error ret;
Patrick Barrett 0:c7393ae16c16 418 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 419 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 420 ret |= coap_set_type(pdu, CT_CON);
Patrick Barrett 0:c7393ae16c16 421 ret |= coap_set_code(pdu, CC_POST);
Patrick Barrett 0:c7393ae16c16 422 ret |= coap_set_mid(pdu, message_id_counter++);
Patrick Barrett 0:c7393ae16c16 423 ret |= coap_set_token(pdu, rand(), 2);
Patrick Barrett 0:c7393ae16c16 424 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"provision", 9);
Patrick Barrett 0:c7393ae16c16 425 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"activate", 8);
Patrick Barrett 0:c7393ae16c16 426 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)vendor, strlen(vendor));
Patrick Barrett 0:c7393ae16c16 427 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)model, strlen(model));
Patrick Barrett 0:c7393ae16c16 428 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)serial_number, strlen(serial_number));
Patrick Barrett 0:c7393ae16c16 429
Patrick Barrett 0:c7393ae16c16 430 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 431 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 432
Patrick Barrett 0:c7393ae16c16 433 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 434 }
Patrick Barrett 0:c7393ae16c16 435
Patrick Barrett 0:c7393ae16c16 436 exo_error exo_build_msg_read(coap_pdu *pdu, const char *alias)
Patrick Barrett 0:c7393ae16c16 437 {
Patrick Barrett 0:c7393ae16c16 438 coap_error ret;
Patrick Barrett 0:c7393ae16c16 439 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 440 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 441 ret |= coap_set_type(pdu, CT_CON);
Patrick Barrett 0:c7393ae16c16 442 ret |= coap_set_code(pdu, CC_GET);
Patrick Barrett 0:c7393ae16c16 443 ret |= coap_set_mid(pdu, message_id_counter++);
Patrick Barrett 0:c7393ae16c16 444 ret |= coap_set_token(pdu, rand(), 2);
Patrick Barrett 0:c7393ae16c16 445 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"1a", 2);
Patrick Barrett 0:c7393ae16c16 446 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)alias, strlen(alias));
Patrick Barrett 0:c7393ae16c16 447 ret |= coap_add_option(pdu, CON_URI_QUERY, (uint8_t*)cik, 40);
Patrick Barrett 0:c7393ae16c16 448
Patrick Barrett 0:c7393ae16c16 449 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 450 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 451
Patrick Barrett 0:c7393ae16c16 452 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 453 }
Patrick Barrett 0:c7393ae16c16 454
Patrick Barrett 0:c7393ae16c16 455 exo_error exo_build_msg_observe(coap_pdu *pdu, const char *alias)
Patrick Barrett 0:c7393ae16c16 456 {
Patrick Barrett 0:c7393ae16c16 457 uint8_t obs_opt = 0;
Patrick Barrett 0:c7393ae16c16 458 coap_error ret;
Patrick Barrett 0:c7393ae16c16 459 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 460 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 461 ret |= coap_set_type(pdu, CT_CON);
Patrick Barrett 0:c7393ae16c16 462 ret |= coap_set_code(pdu, CC_GET);
Patrick Barrett 0:c7393ae16c16 463 ret |= coap_set_mid(pdu, message_id_counter++);
Patrick Barrett 0:c7393ae16c16 464 ret |= coap_set_token(pdu, rand(), 2);
Patrick Barrett 0:c7393ae16c16 465 ret |= coap_add_option(pdu, CON_OBSERVE, &obs_opt, 1);
Patrick Barrett 0:c7393ae16c16 466 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"1a", 2);
Patrick Barrett 0:c7393ae16c16 467 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)alias, strlen(alias));
Patrick Barrett 0:c7393ae16c16 468 ret |= coap_add_option(pdu, CON_URI_QUERY, (uint8_t*)cik, 40);
Patrick Barrett 0:c7393ae16c16 469
Patrick Barrett 0:c7393ae16c16 470 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 471 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 472
Patrick Barrett 0:c7393ae16c16 473 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 474 }
Patrick Barrett 0:c7393ae16c16 475
Patrick Barrett 0:c7393ae16c16 476 exo_error exo_build_msg_write(coap_pdu *pdu, const char *alias, const char *value)
Patrick Barrett 0:c7393ae16c16 477 {
Patrick Barrett 0:c7393ae16c16 478 coap_error ret;
Patrick Barrett 0:c7393ae16c16 479 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 480 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 481 ret |= coap_set_type(pdu, CT_CON);
Patrick Barrett 0:c7393ae16c16 482 ret |= coap_set_code(pdu, CC_POST);
Patrick Barrett 0:c7393ae16c16 483 ret |= coap_set_mid(pdu, message_id_counter++);
Patrick Barrett 0:c7393ae16c16 484 ret |= coap_set_token(pdu, rand(), 2);
Patrick Barrett 0:c7393ae16c16 485 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"1a", 2);
Patrick Barrett 0:c7393ae16c16 486 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)alias, strlen(alias));
Patrick Barrett 0:c7393ae16c16 487 ret |= coap_add_option(pdu, CON_URI_QUERY, (uint8_t*)cik, 40);
Patrick Barrett 0:c7393ae16c16 488 ret |= coap_set_payload(pdu, (uint8_t *)value, strlen(value));
Patrick Barrett 0:c7393ae16c16 489
Patrick Barrett 0:c7393ae16c16 490 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 491 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 492
Patrick Barrett 0:c7393ae16c16 493 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 494 }
Patrick Barrett 0:c7393ae16c16 495
Patrick Barrett 0:c7393ae16c16 496 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 497 {
Patrick Barrett 0:c7393ae16c16 498 coap_error ret;
Patrick Barrett 0:c7393ae16c16 499 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 500 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 501 ret |= coap_set_type(pdu, CT_RST);
Patrick Barrett 0:c7393ae16c16 502 ret |= coap_set_code(pdu, CC_EMPTY);
Patrick Barrett 0:c7393ae16c16 503 ret |= coap_set_mid(pdu, mid);
Patrick Barrett 0:c7393ae16c16 504 ret |= coap_set_token(pdu, token, tkl);
Patrick Barrett 0:c7393ae16c16 505
Patrick Barrett 0:c7393ae16c16 506 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 507 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 508
Patrick Barrett 0:c7393ae16c16 509 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 510 }
Patrick Barrett 0:c7393ae16c16 511
Patrick Barrett 0:c7393ae16c16 512 exo_error exo_build_msg_ack(coap_pdu *pdu, const uint16_t mid)
Patrick Barrett 0:c7393ae16c16 513 {
Patrick Barrett 0:c7393ae16c16 514 coap_error ret;
Patrick Barrett 0:c7393ae16c16 515 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 516 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 517 ret |= coap_set_type(pdu, CT_ACK);
Patrick Barrett 0:c7393ae16c16 518 ret |= coap_set_code(pdu, CC_EMPTY);
Patrick Barrett 0:c7393ae16c16 519 ret |= coap_set_mid(pdu, mid);
Patrick Barrett 0:c7393ae16c16 520
Patrick Barrett 0:c7393ae16c16 521 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 522 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 523
Patrick Barrett 0:c7393ae16c16 524 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 525 }
Patrick Barrett 0:c7393ae16c16 526
Patrick Barrett 0:c7393ae16c16 527 uint8_t exo_validate_cik(const char *cik)
Patrick Barrett 0:c7393ae16c16 528 {
Patrick Barrett 0:c7393ae16c16 529 uint8_t i;
Patrick Barrett 0:c7393ae16c16 530
Patrick Barrett 0:c7393ae16c16 531 for (i = 0; i < CIK_LENGTH; i++) {
Patrick Barrett 0:c7393ae16c16 532 if (!((cik[i] >= 'a' && cik[i] <= 'f') ||
Patrick Barrett 0:c7393ae16c16 533 (cik[i] >= '0' && cik[i] <= '9'))) {
Patrick Barrett 0:c7393ae16c16 534 return 1;
Patrick Barrett 0:c7393ae16c16 535 }
Patrick Barrett 0:c7393ae16c16 536 }
Patrick Barrett 0:c7393ae16c16 537
Patrick Barrett 0:c7393ae16c16 538 return 0;
Patrick Barrett 0:c7393ae16c16 539 }
Patrick Barrett 0:c7393ae16c16 540