The (alpha of the) official Exosite library, CoAP version.

NOTE: This mirror repository may be out of date, check the main repo for changes. If there are any remind me to update this mirror.

This is an unstable alpha of the Official Exosite library, there are known issues with the port to this platform. You probably shouldn't use this library yet if you just want to get things done.

This version uses CoAP for the application protocol.

Committer:
Patrick Barrett
Date:
Mon Dec 22 14:25:39 2014 -0600
Revision:
10:76deeaebfafb
Parent:
0:c7393ae16c16
Child:
11:08bae8fb9824
fixes for auto-re-observe

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 10:76deeaebfafb 180 op->obs_seq = 0;
Patrick Barrett 0:c7393ae16c16 181 }
Patrick Barrett 0:c7393ae16c16 182
Patrick Barrett 0:c7393ae16c16 183 void exo_op_done(exo_op *op)
Patrick Barrett 0:c7393ae16c16 184 {
Patrick Barrett 0:c7393ae16c16 185 if (exo_is_op_subscribe(op)) {
Patrick Barrett 0:c7393ae16c16 186 op->state = EXO_REQUEST_SUBSCRIBED;
Patrick Barrett 0:c7393ae16c16 187 } else {
Patrick Barrett 0:c7393ae16c16 188 exo_op_init(op);
Patrick Barrett 0:c7393ae16c16 189 }
Patrick Barrett 0:c7393ae16c16 190 }
Patrick Barrett 0:c7393ae16c16 191
Patrick Barrett 0:c7393ae16c16 192 uint8_t exo_is_op_valid(exo_op *op)
Patrick Barrett 0:c7393ae16c16 193 {
Patrick Barrett 0:c7393ae16c16 194 return op->type != EXO_NULL;
Patrick Barrett 0:c7393ae16c16 195 }
Patrick Barrett 0:c7393ae16c16 196
Patrick Barrett 0:c7393ae16c16 197 uint8_t exo_is_op_success(exo_op *op)
Patrick Barrett 0:c7393ae16c16 198 {
Patrick Barrett 0:c7393ae16c16 199 return op->state == EXO_REQUEST_SUCCESS;
Patrick Barrett 0:c7393ae16c16 200 }
Patrick Barrett 0:c7393ae16c16 201
Patrick Barrett 0:c7393ae16c16 202 uint8_t exo_is_op_finished(exo_op *op)
Patrick Barrett 0:c7393ae16c16 203 {
Patrick Barrett 0:c7393ae16c16 204 return op->state == EXO_REQUEST_SUCCESS || op->state == EXO_REQUEST_ERROR;
Patrick Barrett 0:c7393ae16c16 205 }
Patrick Barrett 0:c7393ae16c16 206
Patrick Barrett 0:c7393ae16c16 207 uint8_t exo_is_op_read(exo_op *op)
Patrick Barrett 0:c7393ae16c16 208 {
Patrick Barrett 0:c7393ae16c16 209 return op->type == EXO_READ;
Patrick Barrett 0:c7393ae16c16 210 }
Patrick Barrett 0:c7393ae16c16 211
Patrick Barrett 0:c7393ae16c16 212 uint8_t exo_is_op_subscribe(exo_op *op)
Patrick Barrett 0:c7393ae16c16 213 {
Patrick Barrett 0:c7393ae16c16 214 return op->type == EXO_SUBSCRIBE;
Patrick Barrett 0:c7393ae16c16 215 }
Patrick Barrett 0:c7393ae16c16 216
Patrick Barrett 0:c7393ae16c16 217 uint8_t exo_is_op_write(exo_op *op)
Patrick Barrett 0:c7393ae16c16 218 {
Patrick Barrett 0:c7393ae16c16 219 return op->type == EXO_WRITE;
Patrick Barrett 0:c7393ae16c16 220 }
Patrick Barrett 0:c7393ae16c16 221
Patrick Barrett 0:c7393ae16c16 222
Patrick Barrett 0:c7393ae16c16 223 /*!
Patrick Barrett 0:c7393ae16c16 224 * \brief Performs queued operations with the Exosite One Platform
Patrick Barrett 0:c7393ae16c16 225 *
Patrick Barrett 0:c7393ae16c16 226 * Queues a request to read a dataport from the Exosite One Platform. If the
Patrick Barrett 0:c7393ae16c16 227 * request is successful the provided callback will be called with a single
Patrick Barrett 0:c7393ae16c16 228 * parameter, a pointer to the result as a C string.
Patrick Barrett 0:c7393ae16c16 229 *
Patrick Barrett 0:c7393ae16c16 230 * \param[in] alias Alias of dataport to read from
Patrick Barrett 0:c7393ae16c16 231 * \param[in] callback Function pointer to call on success
Patrick Barrett 0:c7393ae16c16 232 *
Patrick Barrett 0:c7393ae16c16 233 * \return EXO_STATE, EXO_OK on success or error code
Patrick Barrett 0:c7393ae16c16 234 *
Patrick Barrett 0:c7393ae16c16 235 */
Patrick Barrett 0:c7393ae16c16 236 exo_state exo_operate(exo_op *op, uint8_t count)
Patrick Barrett 0:c7393ae16c16 237 {
Patrick Barrett 0:c7393ae16c16 238 uint8_t buf[576];
Patrick Barrett 0:c7393ae16c16 239 coap_pdu pdu;
Patrick Barrett 0:c7393ae16c16 240 coap_payload payload;
Patrick Barrett 0:c7393ae16c16 241 int i;
Patrick Barrett 0:c7393ae16c16 242 uint64_t now = exopal_get_time();
Patrick Barrett 0:c7393ae16c16 243
Patrick Barrett 0:c7393ae16c16 244 pdu.buf = buf;
Patrick Barrett 0:c7393ae16c16 245 pdu.max = 576;
Patrick Barrett 0:c7393ae16c16 246 pdu.len = 0;
Patrick Barrett 0:c7393ae16c16 247
Patrick Barrett 0:c7393ae16c16 248 // receive a UDP packet if one or more waiting
Patrick Barrett 0:c7393ae16c16 249 while (exopal_udp_recv(pdu.buf, pdu.max, &pdu.len) == 0) {
Patrick Barrett 0:c7393ae16c16 250 if (coap_validate_pkt(&pdu) != CE_NONE)
Patrick Barrett 0:c7393ae16c16 251 continue; //Invalid Packet, Ignore
Patrick Barrett 0:c7393ae16c16 252
Patrick Barrett 0:c7393ae16c16 253 for (i = 0; i < count; i++) {
Patrick Barrett 0:c7393ae16c16 254 if (op[i].state == EXO_REQUEST_PENDING && op[i].mid == coap_get_mid(&pdu)) {
Patrick Barrett 0:c7393ae16c16 255 //have a reply to a message, process
Patrick Barrett 0:c7393ae16c16 256 if (coap_get_code_class(&pdu) == 2) {
Patrick Barrett 0:c7393ae16c16 257 payload = coap_get_payload(&pdu);
Patrick Barrett 0:c7393ae16c16 258 switch(op[i].type){
Patrick Barrett 0:c7393ae16c16 259 case EXO_READ:
Patrick Barrett 0:c7393ae16c16 260 if (payload.len == 0) {
Patrick Barrett 0:c7393ae16c16 261 op[i].value = 0;
Patrick Barrett 0:c7393ae16c16 262 } else if (payload.len+1 > op[i].value_max || op[i].value == 0) {
Patrick Barrett 0:c7393ae16c16 263 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 0:c7393ae16c16 264 } else{
Patrick Barrett 0:c7393ae16c16 265 memcpy(op[i].value, payload.val, payload.len);
Patrick Barrett 0:c7393ae16c16 266 op[i].value[payload.len] = 0;
Patrick Barrett 0:c7393ae16c16 267 op[i].state = EXO_REQUEST_SUCCESS;
Patrick Barrett 0:c7393ae16c16 268 }
Patrick Barrett 0:c7393ae16c16 269 break;
Patrick Barrett 0:c7393ae16c16 270 case EXO_SUBSCRIBE:
Patrick Barrett 0:c7393ae16c16 271 if (payload.len == 0) {
Patrick Barrett 0:c7393ae16c16 272 op[i].value = 0;
Patrick Barrett 0:c7393ae16c16 273 } else if (payload.len+1 > op[i].value_max || op[i].value == 0) {
Patrick Barrett 0:c7393ae16c16 274 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 0:c7393ae16c16 275 } else{
Patrick Barrett 0:c7393ae16c16 276 memcpy(op[i].value, payload.val, payload.len);
Patrick Barrett 0:c7393ae16c16 277 op[i].value[payload.len] = 0;
Patrick Barrett 0:c7393ae16c16 278 op[i].state = EXO_REQUEST_SUCCESS;
Patrick Barrett 10:76deeaebfafb 279 op[i].timeout = exopal_get_time() + 120000000 + (rand() % 15 * 100000);
Patrick Barrett 0:c7393ae16c16 280 }
Patrick Barrett 0:c7393ae16c16 281 break;
Patrick Barrett 0:c7393ae16c16 282 case EXO_WRITE:
Patrick Barrett 0:c7393ae16c16 283 op[i].state = EXO_REQUEST_SUCCESS;
Patrick Barrett 0:c7393ae16c16 284 break;
Patrick Barrett 0:c7393ae16c16 285 default:
Patrick Barrett 0:c7393ae16c16 286 break;
Patrick Barrett 0:c7393ae16c16 287 }
Patrick Barrett 0:c7393ae16c16 288 } else {
Patrick Barrett 0:c7393ae16c16 289 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 0:c7393ae16c16 290 }
Patrick Barrett 0:c7393ae16c16 291 break;
Patrick Barrett 0:c7393ae16c16 292 }else if (op[i].state == EXO_REQUEST_SUBSCRIBED && coap_get_token(&pdu) == op[i].token) {
Patrick Barrett 0:c7393ae16c16 293
Patrick Barrett 0:c7393ae16c16 294 coap_option opt;
Patrick Barrett 0:c7393ae16c16 295 uint32_t new_seq = 0;
Patrick Barrett 0:c7393ae16c16 296 opt = coap_get_option_by_num(&pdu, CON_OBSERVE, 0);
Patrick Barrett 0:c7393ae16c16 297 for (int j = 0; j < opt.len; j++) {
Patrick Barrett 0:c7393ae16c16 298 new_seq = (new_seq << (8*j)) | opt.val[j];
Patrick Barrett 0:c7393ae16c16 299 }
Patrick Barrett 0:c7393ae16c16 300
Patrick Barrett 0:c7393ae16c16 301 payload = coap_get_payload(&pdu);
Patrick Barrett 0:c7393ae16c16 302 if (payload.len == 0) {
Patrick Barrett 0:c7393ae16c16 303 op[i].value = 0;
Patrick Barrett 0:c7393ae16c16 304 } else if (payload.len+1 > op[i].value_max || op[i].value == 0) {
Patrick Barrett 0:c7393ae16c16 305 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 0:c7393ae16c16 306 } else{
Patrick Barrett 0:c7393ae16c16 307 memcpy(op[i].value, payload.val, payload.len);
Patrick Barrett 0:c7393ae16c16 308 op[i].value[payload.len] = 0;
Patrick Barrett 0:c7393ae16c16 309 op[i].mid = coap_get_mid(&pdu);
Patrick Barrett 0:c7393ae16c16 310 // TODO: User proper logic to ensure it's a new value not a different, but old one.
Patrick Barrett 0:c7393ae16c16 311 if (op[i].obs_seq != new_seq) {
Patrick Barrett 0:c7393ae16c16 312 op[i].state = EXO_REQUEST_SUB_ACK_NEW;
Patrick Barrett 0:c7393ae16c16 313 op[i].obs_seq = new_seq;
Patrick Barrett 0:c7393ae16c16 314 } else {
Patrick Barrett 0:c7393ae16c16 315 op[i].state = EXO_REQUEST_SUB_ACK;
Patrick Barrett 0:c7393ae16c16 316 }
Patrick Barrett 0:c7393ae16c16 317 }
Patrick Barrett 0:c7393ae16c16 318 break;
Patrick Barrett 0:c7393ae16c16 319 }
Patrick Barrett 0:c7393ae16c16 320 }
Patrick Barrett 0:c7393ae16c16 321
Patrick Barrett 0:c7393ae16c16 322 if (i == count){
Patrick Barrett 0:c7393ae16c16 323 if (coap_get_type(&pdu) == CT_CON) {
Patrick Barrett 0:c7393ae16c16 324 // this can't fail
Patrick Barrett 0:c7393ae16c16 325 exo_build_msg_rst(&pdu, coap_get_mid(&pdu), coap_get_token(&pdu), coap_get_tkl(&pdu));
Patrick Barrett 0:c7393ae16c16 326
Patrick Barrett 0:c7393ae16c16 327 // best effort, don't bother checking if it failed, nothing we can do it
Patrick Barrett 0:c7393ae16c16 328 // it did anyway
Patrick Barrett 0:c7393ae16c16 329 exopal_udp_send(pdu.buf, pdu.len);
Patrick Barrett 0:c7393ae16c16 330 }
Patrick Barrett 0:c7393ae16c16 331
Patrick Barrett 0:c7393ae16c16 332 break;
Patrick Barrett 0:c7393ae16c16 333 }
Patrick Barrett 0:c7393ae16c16 334 }
Patrick Barrett 0:c7393ae16c16 335
Patrick Barrett 0:c7393ae16c16 336 // process all requests that need something done
Patrick Barrett 0:c7393ae16c16 337 for (i = 0; i < count; i++) {
Patrick Barrett 0:c7393ae16c16 338 switch (op[i].state) {
Patrick Barrett 0:c7393ae16c16 339 case EXO_REQUEST_NEW:
Patrick Barrett 0:c7393ae16c16 340 // Build and Send Request
Patrick Barrett 0:c7393ae16c16 341 switch (op[i].type) {
Patrick Barrett 0:c7393ae16c16 342 case EXO_READ:
Patrick Barrett 0:c7393ae16c16 343 exo_build_msg_read(&pdu, op[i].alias);
Patrick Barrett 0:c7393ae16c16 344 break;
Patrick Barrett 0:c7393ae16c16 345 case EXO_SUBSCRIBE:
Patrick Barrett 0:c7393ae16c16 346 exo_build_msg_observe(&pdu, op[i].alias);
Patrick Barrett 0:c7393ae16c16 347 break;
Patrick Barrett 0:c7393ae16c16 348 case EXO_WRITE:
Patrick Barrett 0:c7393ae16c16 349 exo_build_msg_write(&pdu, op[i].alias, op[i].value);
Patrick Barrett 0:c7393ae16c16 350 break;
Patrick Barrett 0:c7393ae16c16 351 default:
Patrick Barrett 0:c7393ae16c16 352 op[i].type = EXO_NULL;
Patrick Barrett 0:c7393ae16c16 353 continue;
Patrick Barrett 0:c7393ae16c16 354 }
Patrick Barrett 0:c7393ae16c16 355
Patrick Barrett 0:c7393ae16c16 356 if (exopal_udp_send(pdu.buf, pdu.len) == 0) {
Patrick Barrett 0:c7393ae16c16 357 op[i].state = EXO_REQUEST_PENDING;
Patrick Barrett 0:c7393ae16c16 358 op[i].timeout = exopal_get_time() + 4000000;
Patrick Barrett 0:c7393ae16c16 359 op[i].mid = coap_get_mid(&pdu);
Patrick Barrett 0:c7393ae16c16 360 op[i].token = coap_get_token(&pdu);
Patrick Barrett 0:c7393ae16c16 361 }
Patrick Barrett 0:c7393ae16c16 362
Patrick Barrett 0:c7393ae16c16 363 break;
Patrick Barrett 10:76deeaebfafb 364 case EXO_REQUEST_SUBSCRIBED:
Patrick Barrett 0:c7393ae16c16 365 case EXO_REQUEST_PENDING:
Patrick Barrett 0:c7393ae16c16 366 // check if pending requests have reached timeout
Patrick Barrett 0:c7393ae16c16 367 if (op[i].timeout <= now){
Patrick Barrett 0:c7393ae16c16 368 switch (op[i].type) {
Patrick Barrett 0:c7393ae16c16 369 case EXO_READ:
Patrick Barrett 0:c7393ae16c16 370 case EXO_WRITE:
Patrick Barrett 0:c7393ae16c16 371 // TODO: may want to do some sort of retry system
Patrick Barrett 0:c7393ae16c16 372 op[i].state = EXO_REQUEST_ERROR;
Patrick Barrett 0:c7393ae16c16 373 break;
Patrick Barrett 0:c7393ae16c16 374 case EXO_SUBSCRIBE:
Patrick Barrett 0:c7393ae16c16 375 // force a new observe request
Patrick Barrett 0:c7393ae16c16 376 op[i].state = EXO_REQUEST_NEW;
Patrick Barrett 0:c7393ae16c16 377 break;
Patrick Barrett 0:c7393ae16c16 378 default:
Patrick Barrett 0:c7393ae16c16 379 break;
Patrick Barrett 0:c7393ae16c16 380 }
Patrick Barrett 0:c7393ae16c16 381 }
Patrick Barrett 0:c7393ae16c16 382 break;
Patrick Barrett 0:c7393ae16c16 383 case EXO_REQUEST_SUB_ACK_NEW:
Patrick Barrett 0:c7393ae16c16 384 case EXO_REQUEST_SUB_ACK:
Patrick Barrett 0:c7393ae16c16 385 // send ack for observe notification
Patrick Barrett 0:c7393ae16c16 386 exo_build_msg_ack(&pdu, coap_get_mid(&pdu));
Patrick Barrett 0:c7393ae16c16 387
Patrick Barrett 0:c7393ae16c16 388 if (exopal_udp_send(pdu.buf, pdu.len) == 0) {
Patrick Barrett 0:c7393ae16c16 389 if (op[i].state == EXO_REQUEST_SUB_ACK)
Patrick Barrett 0:c7393ae16c16 390 op[i].state = EXO_REQUEST_SUBSCRIBED;
Patrick Barrett 0:c7393ae16c16 391 else if (op[i].state == EXO_REQUEST_SUB_ACK_NEW)
Patrick Barrett 0:c7393ae16c16 392 op[i].state = EXO_REQUEST_SUCCESS;
Patrick Barrett 0:c7393ae16c16 393
Patrick Barrett 0:c7393ae16c16 394 // TODO: this should get set to Max-Age value, hard coding 120 s
Patrick Barrett 10:76deeaebfafb 395 op[i].timeout = exopal_get_time() + 120000000 + (rand() % 15 * 100000);
Patrick Barrett 0:c7393ae16c16 396 }
Patrick Barrett 0:c7393ae16c16 397 break;
Patrick Barrett 0:c7393ae16c16 398 default:
Patrick Barrett 0:c7393ae16c16 399 break;
Patrick Barrett 0:c7393ae16c16 400 }
Patrick Barrett 0:c7393ae16c16 401 }
Patrick Barrett 0:c7393ae16c16 402
Patrick Barrett 0:c7393ae16c16 403 for (i = 0; i < count; i++) {
Patrick Barrett 0:c7393ae16c16 404 if (op[i].state == EXO_REQUEST_NEW)
Patrick Barrett 0:c7393ae16c16 405 return EXO_BUSY;
Patrick Barrett 0:c7393ae16c16 406 }
Patrick Barrett 0:c7393ae16c16 407
Patrick Barrett 0:c7393ae16c16 408 for (i = 0; i < count; i++) {
Patrick Barrett 0:c7393ae16c16 409 if (op[i].state == EXO_REQUEST_PENDING)
Patrick Barrett 0:c7393ae16c16 410 return EXO_WAITING;
Patrick Barrett 0:c7393ae16c16 411 }
Patrick Barrett 0:c7393ae16c16 412
Patrick Barrett 0:c7393ae16c16 413 return EXO_IDLE;
Patrick Barrett 0:c7393ae16c16 414 }
Patrick Barrett 0:c7393ae16c16 415
Patrick Barrett 0:c7393ae16c16 416 // Internal Functions
Patrick Barrett 0:c7393ae16c16 417
Patrick Barrett 0:c7393ae16c16 418 exo_error exo_build_msg_activate(coap_pdu *pdu, const char *vendor, const char *model, const char *serial_number)
Patrick Barrett 0:c7393ae16c16 419 {
Patrick Barrett 0:c7393ae16c16 420 coap_error ret;
Patrick Barrett 0:c7393ae16c16 421 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 422 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 423 ret |= coap_set_type(pdu, CT_CON);
Patrick Barrett 0:c7393ae16c16 424 ret |= coap_set_code(pdu, CC_POST);
Patrick Barrett 0:c7393ae16c16 425 ret |= coap_set_mid(pdu, message_id_counter++);
Patrick Barrett 0:c7393ae16c16 426 ret |= coap_set_token(pdu, rand(), 2);
Patrick Barrett 0:c7393ae16c16 427 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"provision", 9);
Patrick Barrett 0:c7393ae16c16 428 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"activate", 8);
Patrick Barrett 0:c7393ae16c16 429 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)vendor, strlen(vendor));
Patrick Barrett 0:c7393ae16c16 430 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)model, strlen(model));
Patrick Barrett 0:c7393ae16c16 431 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)serial_number, strlen(serial_number));
Patrick Barrett 0:c7393ae16c16 432
Patrick Barrett 0:c7393ae16c16 433 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 434 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 435
Patrick Barrett 0:c7393ae16c16 436 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 437 }
Patrick Barrett 0:c7393ae16c16 438
Patrick Barrett 0:c7393ae16c16 439 exo_error exo_build_msg_read(coap_pdu *pdu, const char *alias)
Patrick Barrett 0:c7393ae16c16 440 {
Patrick Barrett 0:c7393ae16c16 441 coap_error ret;
Patrick Barrett 0:c7393ae16c16 442 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 443 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 444 ret |= coap_set_type(pdu, CT_CON);
Patrick Barrett 0:c7393ae16c16 445 ret |= coap_set_code(pdu, CC_GET);
Patrick Barrett 0:c7393ae16c16 446 ret |= coap_set_mid(pdu, message_id_counter++);
Patrick Barrett 0:c7393ae16c16 447 ret |= coap_set_token(pdu, rand(), 2);
Patrick Barrett 0:c7393ae16c16 448 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"1a", 2);
Patrick Barrett 0:c7393ae16c16 449 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)alias, strlen(alias));
Patrick Barrett 0:c7393ae16c16 450 ret |= coap_add_option(pdu, CON_URI_QUERY, (uint8_t*)cik, 40);
Patrick Barrett 0:c7393ae16c16 451
Patrick Barrett 0:c7393ae16c16 452 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 453 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 454
Patrick Barrett 0:c7393ae16c16 455 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 456 }
Patrick Barrett 0:c7393ae16c16 457
Patrick Barrett 0:c7393ae16c16 458 exo_error exo_build_msg_observe(coap_pdu *pdu, const char *alias)
Patrick Barrett 0:c7393ae16c16 459 {
Patrick Barrett 0:c7393ae16c16 460 uint8_t obs_opt = 0;
Patrick Barrett 0:c7393ae16c16 461 coap_error ret;
Patrick Barrett 0:c7393ae16c16 462 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 463 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 464 ret |= coap_set_type(pdu, CT_CON);
Patrick Barrett 0:c7393ae16c16 465 ret |= coap_set_code(pdu, CC_GET);
Patrick Barrett 0:c7393ae16c16 466 ret |= coap_set_mid(pdu, message_id_counter++);
Patrick Barrett 0:c7393ae16c16 467 ret |= coap_set_token(pdu, rand(), 2);
Patrick Barrett 0:c7393ae16c16 468 ret |= coap_add_option(pdu, CON_OBSERVE, &obs_opt, 1);
Patrick Barrett 0:c7393ae16c16 469 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"1a", 2);
Patrick Barrett 0:c7393ae16c16 470 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)alias, strlen(alias));
Patrick Barrett 0:c7393ae16c16 471 ret |= coap_add_option(pdu, CON_URI_QUERY, (uint8_t*)cik, 40);
Patrick Barrett 0:c7393ae16c16 472
Patrick Barrett 0:c7393ae16c16 473 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 474 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 475
Patrick Barrett 0:c7393ae16c16 476 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 477 }
Patrick Barrett 0:c7393ae16c16 478
Patrick Barrett 0:c7393ae16c16 479 exo_error exo_build_msg_write(coap_pdu *pdu, const char *alias, const char *value)
Patrick Barrett 0:c7393ae16c16 480 {
Patrick Barrett 0:c7393ae16c16 481 coap_error ret;
Patrick Barrett 0:c7393ae16c16 482 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 483 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 484 ret |= coap_set_type(pdu, CT_CON);
Patrick Barrett 0:c7393ae16c16 485 ret |= coap_set_code(pdu, CC_POST);
Patrick Barrett 0:c7393ae16c16 486 ret |= coap_set_mid(pdu, message_id_counter++);
Patrick Barrett 0:c7393ae16c16 487 ret |= coap_set_token(pdu, rand(), 2);
Patrick Barrett 0:c7393ae16c16 488 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"1a", 2);
Patrick Barrett 0:c7393ae16c16 489 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)alias, strlen(alias));
Patrick Barrett 0:c7393ae16c16 490 ret |= coap_add_option(pdu, CON_URI_QUERY, (uint8_t*)cik, 40);
Patrick Barrett 0:c7393ae16c16 491 ret |= coap_set_payload(pdu, (uint8_t *)value, strlen(value));
Patrick Barrett 0:c7393ae16c16 492
Patrick Barrett 0:c7393ae16c16 493 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 494 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 495
Patrick Barrett 0:c7393ae16c16 496 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 497 }
Patrick Barrett 0:c7393ae16c16 498
Patrick Barrett 0:c7393ae16c16 499 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 500 {
Patrick Barrett 0:c7393ae16c16 501 coap_error ret;
Patrick Barrett 0:c7393ae16c16 502 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 503 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 504 ret |= coap_set_type(pdu, CT_RST);
Patrick Barrett 0:c7393ae16c16 505 ret |= coap_set_code(pdu, CC_EMPTY);
Patrick Barrett 0:c7393ae16c16 506 ret |= coap_set_mid(pdu, mid);
Patrick Barrett 0:c7393ae16c16 507 ret |= coap_set_token(pdu, token, tkl);
Patrick Barrett 0:c7393ae16c16 508
Patrick Barrett 0:c7393ae16c16 509 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 510 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 511
Patrick Barrett 0:c7393ae16c16 512 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 513 }
Patrick Barrett 0:c7393ae16c16 514
Patrick Barrett 0:c7393ae16c16 515 exo_error exo_build_msg_ack(coap_pdu *pdu, const uint16_t mid)
Patrick Barrett 0:c7393ae16c16 516 {
Patrick Barrett 0:c7393ae16c16 517 coap_error ret;
Patrick Barrett 0:c7393ae16c16 518 coap_init_pdu(pdu);
Patrick Barrett 0:c7393ae16c16 519 ret = coap_set_version(pdu, COAP_V1);
Patrick Barrett 0:c7393ae16c16 520 ret |= coap_set_type(pdu, CT_ACK);
Patrick Barrett 0:c7393ae16c16 521 ret |= coap_set_code(pdu, CC_EMPTY);
Patrick Barrett 0:c7393ae16c16 522 ret |= coap_set_mid(pdu, mid);
Patrick Barrett 0:c7393ae16c16 523
Patrick Barrett 0:c7393ae16c16 524 if (ret != CE_NONE)
Patrick Barrett 0:c7393ae16c16 525 return EXO_GENERAL_ERROR;
Patrick Barrett 0:c7393ae16c16 526
Patrick Barrett 0:c7393ae16c16 527 return EXO_OK;
Patrick Barrett 0:c7393ae16c16 528 }
Patrick Barrett 0:c7393ae16c16 529
Patrick Barrett 0:c7393ae16c16 530 uint8_t exo_validate_cik(const char *cik)
Patrick Barrett 0:c7393ae16c16 531 {
Patrick Barrett 0:c7393ae16c16 532 uint8_t i;
Patrick Barrett 0:c7393ae16c16 533
Patrick Barrett 0:c7393ae16c16 534 for (i = 0; i < CIK_LENGTH; i++) {
Patrick Barrett 0:c7393ae16c16 535 if (!((cik[i] >= 'a' && cik[i] <= 'f') ||
Patrick Barrett 0:c7393ae16c16 536 (cik[i] >= '0' && cik[i] <= '9'))) {
Patrick Barrett 0:c7393ae16c16 537 return 1;
Patrick Barrett 0:c7393ae16c16 538 }
Patrick Barrett 0:c7393ae16c16 539 }
Patrick Barrett 0:c7393ae16c16 540
Patrick Barrett 0:c7393ae16c16 541 return 0;
Patrick Barrett 0:c7393ae16c16 542 }
Patrick Barrett 0:c7393ae16c16 543