Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
exosite.c
00001 /***************************************************************************** 00002 * 00003 * exosite.c - Exosite Activator Library 00004 * Copyright (C) 2015 Exosite LLC 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 00013 * Redistributions in binary form must reproduce the above copyright 00014 * notice, this list of conditions and the following disclaimer in the 00015 * documentation and/or other materials provided with the 00016 * distribution. 00017 * 00018 * Neither the name of Texas Instruments Incorporated nor the names of 00019 * its contributors may be used to endorse or promote products derived 00020 * from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00023 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00024 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00025 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00026 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00027 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00028 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00029 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00030 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00031 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00032 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 * 00034 *****************************************************************************/ 00035 #include "exosite_pal.h" 00036 #include "exosite.h" 00037 #include "coap.h" 00038 00039 #include <stdlib.h> 00040 #include <stdbool.h> 00041 #include <time.h> 00042 #include <string.h> 00043 #include <ctype.h> 00044 00045 // Internal Functions 00046 00047 static void exo_process_waiting_datagrams(exo_op *op, uint8_t count); 00048 static void exo_process_active_ops(exo_op *op, uint8_t count); 00049 exo_error exo_build_msg_activate(coap_pdu *pdu, const char *vendor, const char *model, const char *serial_number); 00050 exo_error exo_build_msg_read(coap_pdu *pdu, const char *alias); 00051 exo_error exo_build_msg_observe(coap_pdu *pdu, const char *alias); 00052 exo_error exo_build_msg_write(coap_pdu *pdu, const char *alias, const char *value); 00053 exo_error exo_build_msg_rst(coap_pdu *pdu, const uint16_t mid, const uint64_t token, const uint8_t tkl); 00054 exo_error exo_build_msg_ack(coap_pdu *pdu, const uint16_t mid); 00055 uint8_t exosite_validate_cik(char *cik); 00056 00057 // Local Variables 00058 static char cik[CIK_LENGTH + 1]; 00059 static const char *vendor; 00060 static const char *model; 00061 static const char *serial; 00062 static uint16_t message_id_counter; 00063 static exo_device_state device_state = EXO_STATE_UNINITIALIZED; 00064 00065 // Internal Constants 00066 static const int MINIMUM_DATAGRAM_SIZE = 576; // RFC791: all hosts must accept minimum of 576 octets 00067 00068 /*! 00069 * \brief Initializes the Exosite library 00070 * 00071 * This **MUST** be called before any other exosite library calls are called. 00072 * 00073 * \param[in] *vendor Pointer to string containing the vendor name 00074 * \param[in] *model Pointer to string containing the model name 00075 * \param[in] *serial Pointer to string containing the serial number 00076 * 00077 * \return EXO_ERROR, EXO_OK on success, else error code 00078 */ 00079 exo_error exo_init(const char *vendor_in, const char *model_in, const char *serial_in) 00080 { 00081 device_state = EXO_STATE_UNINITIALIZED; 00082 00083 if (exopal_init() != 0) { 00084 return EXO_FATAL_ERROR_PAL; 00085 } 00086 00087 srand(time(NULL)); 00088 message_id_counter = rand(); 00089 00090 serial = serial_in; 00091 vendor = vendor_in; 00092 model = model_in; 00093 00094 if (exopal_retrieve_cik(cik) > 1){ 00095 return EXO_FATAL_ERROR_PAL; 00096 } else { 00097 cik[40] = 0; 00098 } 00099 00100 if (exopal_udp_sock() != 0) { 00101 return EXO_FATAL_ERROR_PAL; 00102 } 00103 00104 device_state = EXO_STATE_INITIALIZED; 00105 00106 return EXO_OK; 00107 } 00108 00109 /*! 00110 * \brief Queues a Write to the Exosite One Platform 00111 * 00112 * Queues a request to write to a dataport. 00113 * 00114 * \param[in] *alias Alias of dataport to write to, pointer must remain 00115 * valid until the request has been sent. 00116 * \param[in] callback Function pointer to call on success 00117 * 00118 * \return EXO_ERROR, EXO_OK on success or error code 00119 * 00120 */ 00121 00122 void exo_write(exo_op *op, const char * alias, const char * value) 00123 { 00124 op->type = EXO_WRITE; 00125 op->state = EXO_REQUEST_NEW; 00126 op->alias = alias; 00127 op->value = (char *)value; // this is kinda dirty, I know 00128 op->value_max = 0; 00129 op->mid = 0; 00130 } 00131 00132 /*! 00133 * \brief Queues a Read from the Exosite One Platform 00134 * 00135 * Queues a request to read a dataport. If the request is successful, the 00136 * provided callback will be called with a single parameter, a pointer to the 00137 * result as a C string. 00138 * 00139 * \param[in] *alias Alias of dataport to read from, pointer must remain 00140 * valid until the request has been sent. 00141 * \param[in] callback Function pointer to call on success 00142 * 00143 * \return EXO_ERROR, EXO_OK on success or error code 00144 * 00145 */ 00146 void exo_read(exo_op *op, const char * alias, char * value, const size_t value_max) 00147 { 00148 op->type = EXO_READ; 00149 op->state = EXO_REQUEST_NEW; 00150 op->alias = alias; 00151 op->value = value; 00152 op->value_max = value_max; 00153 op->mid = 0; 00154 } 00155 00156 /*! 00157 * \brief Subscribes to a Dataport on the Exosite One Platform 00158 * 00159 * Begins a subscription to a dataport The callback is called any time the 00160 * value is updated as well as when the subscription is started. 00161 * 00162 * \param[in] alias Alias of dataport to read from 00163 * \param[in] callback Function pointer to call on change 00164 * 00165 * \return EXO_ERROR, EXO_OK on success or error code 00166 * 00167 */ 00168 void exo_subscribe(exo_op *op, const char * alias, char * value, const size_t value_max) 00169 { 00170 op->type = EXO_SUBSCRIBE; 00171 op->state = EXO_REQUEST_NEW; 00172 op->alias = alias; 00173 op->value = value; 00174 op->value_max = value_max; 00175 op->mid = 0; 00176 } 00177 00178 /*! 00179 * \brief Activates the Device on the Platform 00180 * 00181 * Queues an activation request. Usually only used internally. 00182 * 00183 */ 00184 void exo_activate(exo_op *op) 00185 { 00186 op->type = EXO_ACTIVATE; 00187 op->state = EXO_REQUEST_NEW; 00188 op->alias = NULL; 00189 op->value = NULL; 00190 op->value_max = 0; 00191 op->mid = 0; 00192 } 00193 00194 void exo_op_init(exo_op *op) 00195 { 00196 op->type = EXO_NULL; 00197 op->state = EXO_REQUEST_NULL; 00198 op->alias = NULL; 00199 op->value = NULL; 00200 op->value_max = 0; 00201 op->mid = 0; 00202 op->obs_seq = 0; 00203 op->tkl = 0; 00204 op->token = 0; 00205 op->timeout = 0; 00206 op->retries = 0; 00207 } 00208 00209 void exo_op_done(exo_op *op) 00210 { 00211 if (exo_is_op_subscribe(op)) { 00212 op->state = EXO_REQUEST_SUBSCRIBED; 00213 } else { 00214 exo_op_init(op); 00215 } 00216 } 00217 00218 uint8_t exo_is_op_valid(exo_op *op) 00219 { 00220 return op->type != EXO_NULL; 00221 } 00222 00223 uint8_t exo_is_op_success(exo_op *op) 00224 { 00225 return op->state == EXO_REQUEST_SUCCESS; 00226 } 00227 00228 uint8_t exo_is_op_finished(exo_op *op) 00229 { 00230 return op->state == EXO_REQUEST_SUCCESS || op->state == EXO_REQUEST_ERROR; 00231 } 00232 00233 uint8_t exo_is_op_read(exo_op *op) 00234 { 00235 return op->type == EXO_READ; 00236 } 00237 00238 uint8_t exo_is_op_subscribe(exo_op *op) 00239 { 00240 return op->type == EXO_SUBSCRIBE; 00241 } 00242 00243 uint8_t exo_is_op_write(exo_op *op) 00244 { 00245 return op->type == EXO_WRITE; 00246 } 00247 00248 00249 /*! 00250 * \brief Performs queued operations with the Exosite One Platform 00251 * 00252 * Queues a request to read a dataport from the Exosite One Platform. If the 00253 * request is successful the provided callback will be called with a single 00254 * parameter, a pointer to the result as a C string. 00255 * 00256 * \param[in] alias Alias of dataport to read from 00257 * \param[in] callback Function pointer to call on success 00258 * 00259 * \return EXO_STATE, EXO_OK on success or error code 00260 * 00261 */ 00262 exo_state exo_operate(exo_op *op, uint8_t count) 00263 { 00264 int i; 00265 00266 switch (device_state){ 00267 case EXO_STATE_UNINITIALIZED: 00268 return EXO_ERROR; 00269 case EXO_STATE_INITIALIZED: 00270 case EXO_STATE_BAD_CIK: 00271 if (op[0].state == EXO_REQUEST_NULL || op[0].timeout < exopal_get_time()) 00272 exo_activate(&op[0]); 00273 case EXO_STATE_GOOD: 00274 break; 00275 } 00276 00277 exo_process_waiting_datagrams(op, count); 00278 exo_process_active_ops(op, count); 00279 00280 for (i = 0; i < count; i++) { 00281 if (op[i].state == EXO_REQUEST_NEW) 00282 return EXO_BUSY; 00283 } 00284 00285 for (i = 0; i < count; i++) { 00286 if (op[i].state == EXO_REQUEST_PENDING) 00287 return EXO_WAITING; 00288 } 00289 00290 return EXO_IDLE; 00291 } 00292 00293 // Internal Functions 00294 00295 static void exo_process_waiting_datagrams(exo_op *op, uint8_t count) 00296 { 00297 uint8_t buf[MINIMUM_DATAGRAM_SIZE]; 00298 coap_pdu pdu; 00299 coap_option opt; 00300 coap_payload payload; 00301 int i; 00302 00303 pdu.buf = buf; 00304 pdu.max = MINIMUM_DATAGRAM_SIZE; 00305 pdu.len = 0; 00306 00307 // receive a UDP packet if one or more waiting 00308 while (exopal_udp_recv(pdu.buf, pdu.max, &pdu.len) == 0) { 00309 if (coap_validate_pkt(&pdu) != CE_NONE) 00310 continue; //Invalid Packet, Ignore 00311 00312 for (i = 0; i < count; i++) { 00313 if (coap_get_type(&pdu) == CT_CON || coap_get_type(&pdu) == CT_NON) { 00314 if (op[i].state == EXO_REQUEST_SUBSCRIBED && coap_get_token(&pdu) == op[i].token) { 00315 if (coap_get_code(&pdu) == CC_CONTENT) { 00316 uint32_t new_seq = 0; 00317 opt = coap_get_option_by_num(&pdu, CON_OBSERVE, 0); 00318 for (int j = 0; j < opt.len; j++) { 00319 new_seq = (new_seq << (8*j)) | opt.val[j]; 00320 } 00321 00322 payload = coap_get_payload(&pdu); 00323 if (payload.len == 0) { 00324 op[i].value[0] = '\0'; 00325 } else if (payload.len+1 > op[i].value_max || op[i].value == 0) { 00326 op[i].state = EXO_REQUEST_ERROR; 00327 } else{ 00328 memcpy(op[i].value, payload.val, payload.len); 00329 op[i].value[payload.len] = 0; 00330 op[i].mid = coap_get_mid(&pdu); 00331 // TODO: User proper logic to ensure it's a new value not a different, but old one. 00332 if (op[i].obs_seq != new_seq) { 00333 op[i].state = EXO_REQUEST_SUB_ACK_NEW; 00334 op[i].obs_seq = new_seq; 00335 } else { 00336 op[i].state = EXO_REQUEST_SUB_ACK; 00337 } 00338 00339 opt = coap_get_option_by_num(&pdu, CON_MAX_AGE, 0); 00340 uint8_t max_age = 120; // default, 2 minutes, see RFC4787 Sec 4.3 00341 if (opt.num !=0 && opt.len == 1){ // if has Max-Age option, use it 00342 max_age = opt.val[0]; 00343 } 00344 00345 // Set timeout between Max-Age to Max-Age + ACK_RANDOM_FACTOR (CoAP Defined) 00346 op[i].timeout = exopal_get_time() + (max_age * 1000000) 00347 + (((uint64_t)rand() % 1500000)); 00348 } 00349 } else if (coap_get_code_class(&pdu) != 2) { 00350 op[i].state = EXO_REQUEST_ERROR; 00351 } 00352 break; 00353 } 00354 } else if (coap_get_type(&pdu) == CT_ACK) { 00355 if (op[i].state == EXO_REQUEST_PENDING && op[i].mid == coap_get_mid(&pdu)) { 00356 if (coap_get_code_class(&pdu) == 2) { 00357 switch (op[i].type) { 00358 case EXO_WRITE: 00359 op[i].state = EXO_REQUEST_SUCCESS; 00360 break; 00361 case EXO_READ: 00362 payload = coap_get_payload(&pdu); 00363 if (payload.len == 0) { 00364 op[i].value[0] = '\0'; 00365 } else if (payload.len+1 > op[i].value_max || op[i].value == 0) { 00366 op[i].state = EXO_REQUEST_ERROR; 00367 } else{ 00368 memcpy(op[i].value, payload.val, payload.len); 00369 op[i].value[payload.len] = 0; 00370 op[i].state = EXO_REQUEST_SUCCESS; 00371 } 00372 break; 00373 case EXO_SUBSCRIBE: 00374 payload = coap_get_payload(&pdu); 00375 if (payload.len == 0) { 00376 op[i].value[0] = '\0'; 00377 } else if (payload.len+1 > op[i].value_max || op[i].value == 0) { 00378 op[i].state = EXO_REQUEST_ERROR; 00379 } else{ 00380 memcpy(op[i].value, payload.val, payload.len); 00381 op[i].value[payload.len] = 0; 00382 op[i].state = EXO_REQUEST_SUCCESS; 00383 00384 opt = coap_get_option_by_num(&pdu, CON_MAX_AGE, 0); 00385 uint8_t max_age = 120; // default, 2 minutes, see RFC4787 Sec 4.3 00386 if (opt.num !=0 && opt.len == 1){ // if has Max-Age option, use it 00387 max_age = opt.val[0]; 00388 } 00389 00390 opt = coap_get_option_by_num(&pdu, CON_OBSERVE, 0); 00391 for (int j = 0; j < opt.len; j++) { 00392 op[i].obs_seq = (op[i].obs_seq << (8*j)) | opt.val[j]; 00393 } 00394 00395 // Set timeout between Max-Age to Max-Age + ACK_RANDOM_FACTOR (CoAP Defined) 00396 op[i].timeout = exopal_get_time() + (max_age * 1000000) 00397 + (((uint64_t)rand() % 1500000)); 00398 } 00399 break; 00400 case EXO_ACTIVATE: 00401 payload = coap_get_payload(&pdu); 00402 if (payload.len == CIK_LENGTH) { 00403 memcpy(cik, payload.val, CIK_LENGTH); 00404 cik[CIK_LENGTH] = 0; 00405 op[i].state = EXO_REQUEST_SUCCESS; 00406 exopal_store_cik(cik); 00407 device_state = EXO_STATE_GOOD; 00408 } else { 00409 op[i].state = EXO_REQUEST_ERROR; 00410 } 00411 00412 // We're done with this op now. 00413 exo_op_init(&op[i]); 00414 break; 00415 case EXO_NULL: // pending null request? shouldn't be possible 00416 continue; 00417 } 00418 } else { 00419 op[i].state = EXO_REQUEST_ERROR; 00420 00421 if (coap_get_code(&pdu) == CC_UNAUTHORIZED){ 00422 //device_state = EXO_STATE_BAD_CIK; 00423 00424 if (op[0].type == EXO_NULL || op[0].timeout < exopal_get_time()) 00425 exo_activate(&op[0]); 00426 } else if (coap_get_code(&pdu) == CC_NOT_FOUND) { 00427 device_state = EXO_STATE_GOOD; 00428 } 00429 } 00430 00431 break; 00432 } 00433 00434 } else if (coap_get_type(&pdu) == CT_RST) { 00435 if ((op[i].state == EXO_REQUEST_PENDING || op[i].state == EXO_REQUEST_SUBSCRIBED) && 00436 (op[i].mid == coap_get_mid(&pdu) && op[i].token == coap_get_token(&pdu))){ 00437 op[i].state = EXO_REQUEST_ERROR; 00438 break; 00439 } 00440 } 00441 } 00442 00443 // if the above loop ends normally we don't recognize message, reply RST 00444 if (i == count){ 00445 if (coap_get_type(&pdu) == CT_CON) { 00446 // this can't fail 00447 exo_build_msg_rst(&pdu, coap_get_mid(&pdu), coap_get_token(&pdu), coap_get_tkl(&pdu)); 00448 00449 // best effort, don't bother checking if it failed, nothing we can do it 00450 // it did anyway 00451 exopal_udp_send(pdu.buf, pdu.len); 00452 } 00453 00454 break; 00455 } 00456 } 00457 } 00458 00459 // process all ops that are in an active state 00460 static void exo_process_active_ops(exo_op *op, uint8_t count) 00461 { 00462 uint8_t buf[MINIMUM_DATAGRAM_SIZE]; 00463 coap_pdu pdu; 00464 int i; 00465 uint64_t now = exopal_get_time(); 00466 00467 pdu.buf = buf; 00468 pdu.max = MINIMUM_DATAGRAM_SIZE; 00469 pdu.len = 0; 00470 00471 for (i = 0; i < count; i++) { 00472 switch (op[i].state) { 00473 case EXO_REQUEST_NEW: 00474 // Build and Send Request 00475 switch (op[i].type) { 00476 case EXO_READ: 00477 exo_build_msg_read(&pdu, op[i].alias); 00478 break; 00479 case EXO_SUBSCRIBE: 00480 exo_build_msg_observe(&pdu, op[i].alias); 00481 break; 00482 case EXO_WRITE: 00483 exo_build_msg_write(&pdu, op[i].alias, op[i].value); 00484 break; 00485 case EXO_ACTIVATE: 00486 exo_build_msg_activate(&pdu, vendor, model, serial); 00487 break; 00488 default: 00489 op[i].type = EXO_NULL; 00490 continue; 00491 } 00492 00493 if (exopal_udp_send(pdu.buf, pdu.len) == 0) { 00494 op[i].state = EXO_REQUEST_PENDING; 00495 op[i].timeout = exopal_get_time() + 4000000; 00496 op[i].mid = coap_get_mid(&pdu); 00497 op[i].token = coap_get_token(&pdu); 00498 } 00499 00500 break; 00501 case EXO_REQUEST_SUBSCRIBED: 00502 case EXO_REQUEST_PENDING: 00503 // check if pending requests have reached timeout 00504 if (op[i].timeout <= now){ 00505 switch (op[i].type) { 00506 case EXO_READ: 00507 case EXO_WRITE: 00508 case EXO_ACTIVATE: 00509 if (op[i].retries < COAP_MAX_RETRANSMIT){ 00510 switch (op[i].type) { 00511 case EXO_READ: 00512 exo_build_msg_read(&pdu, op[i].alias); 00513 break; 00514 case EXO_WRITE: 00515 exo_build_msg_write(&pdu, op[i].alias, op[i].value); 00516 break; 00517 case EXO_ACTIVATE: 00518 exo_build_msg_activate(&pdu, vendor, model, serial); 00519 break; 00520 default: 00521 break; 00522 } 00523 00524 // reuse old mid and token 00525 coap_set_mid(&pdu, op[i].mid); 00526 coap_set_token(&pdu, op[i].token, op[i].tkl); 00527 00528 if (exopal_udp_send(pdu.buf, pdu.len) == 0) { 00529 op[i].retries++; 00530 op[i].timeout = exopal_get_time() + (op[i].retries * COAP_PROBING_RATE * 1000000) 00531 + (((uint64_t)rand() % 1500000)); 00532 } 00533 } else { 00534 op[i].state = EXO_REQUEST_ERROR; 00535 } 00536 break; 00537 case EXO_SUBSCRIBE: 00538 // force a new observe request 00539 op[i].state = EXO_REQUEST_NEW; 00540 break; 00541 default: 00542 break; 00543 } 00544 } 00545 break; 00546 case EXO_REQUEST_SUB_ACK_NEW: 00547 case EXO_REQUEST_SUB_ACK: 00548 // send ack for observe notification 00549 exo_build_msg_ack(&pdu, coap_get_mid(&pdu)); 00550 00551 if (exopal_udp_send(pdu.buf, pdu.len) == 0) { 00552 if (op[i].state == EXO_REQUEST_SUB_ACK) 00553 op[i].state = EXO_REQUEST_SUBSCRIBED; 00554 else if (op[i].state == EXO_REQUEST_SUB_ACK_NEW) 00555 op[i].state = EXO_REQUEST_SUCCESS; 00556 } 00557 break; 00558 default: 00559 break; 00560 } 00561 } 00562 } 00563 00564 00565 exo_error exo_build_msg_activate(coap_pdu *pdu, const char *vendor, const char *model, const char *serial_number) 00566 { 00567 coap_error ret; 00568 coap_init_pdu(pdu); 00569 ret = coap_set_version(pdu, COAP_V1); 00570 ret |= coap_set_type(pdu, CT_CON); 00571 ret |= coap_set_code(pdu, CC_POST); 00572 ret |= coap_set_mid(pdu, message_id_counter++); 00573 ret |= coap_set_token(pdu, rand(), 2); 00574 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"provision", 9); 00575 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"activate", 8); 00576 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)vendor, strlen(vendor)); 00577 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)model, strlen(model)); 00578 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)serial_number, strlen(serial_number)); 00579 00580 if (ret != CE_NONE) 00581 return EXO_GENERAL_ERROR; 00582 00583 return EXO_OK; 00584 } 00585 00586 exo_error exo_build_msg_read(coap_pdu *pdu, const char *alias) 00587 { 00588 coap_error ret; 00589 coap_init_pdu(pdu); 00590 ret = coap_set_version(pdu, COAP_V1); 00591 ret |= coap_set_type(pdu, CT_CON); 00592 ret |= coap_set_code(pdu, CC_GET); 00593 ret |= coap_set_mid(pdu, message_id_counter++); 00594 ret |= coap_set_token(pdu, rand(), 2); 00595 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"1a", 2); 00596 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)alias, strlen(alias)); 00597 ret |= coap_add_option(pdu, CON_URI_QUERY, (uint8_t*)cik, 40); 00598 00599 if (ret != CE_NONE) 00600 return EXO_GENERAL_ERROR; 00601 00602 return EXO_OK; 00603 } 00604 00605 exo_error exo_build_msg_observe(coap_pdu *pdu, const char *alias) 00606 { 00607 uint8_t obs_opt = 0; 00608 coap_error ret; 00609 coap_init_pdu(pdu); 00610 ret = coap_set_version(pdu, COAP_V1); 00611 ret |= coap_set_type(pdu, CT_CON); 00612 ret |= coap_set_code(pdu, CC_GET); 00613 ret |= coap_set_mid(pdu, message_id_counter++); 00614 ret |= coap_set_token(pdu, rand(), 2); 00615 ret |= coap_add_option(pdu, CON_OBSERVE, &obs_opt, 1); 00616 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"1a", 2); 00617 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)alias, strlen(alias)); 00618 ret |= coap_add_option(pdu, CON_URI_QUERY, (uint8_t*)cik, 40); 00619 00620 if (ret != CE_NONE) 00621 return EXO_GENERAL_ERROR; 00622 00623 return EXO_OK; 00624 } 00625 00626 exo_error exo_build_msg_write(coap_pdu *pdu, const char *alias, const char *value) 00627 { 00628 coap_error ret; 00629 coap_init_pdu(pdu); 00630 ret = coap_set_version(pdu, COAP_V1); 00631 ret |= coap_set_type(pdu, CT_CON); 00632 ret |= coap_set_code(pdu, CC_POST); 00633 ret |= coap_set_mid(pdu, message_id_counter++); 00634 ret |= coap_set_token(pdu, rand(), 2); 00635 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)"1a", 2); 00636 ret |= coap_add_option(pdu, CON_URI_PATH, (uint8_t*)alias, strlen(alias)); 00637 ret |= coap_add_option(pdu, CON_URI_QUERY, (uint8_t*)cik, 40); 00638 ret |= coap_set_payload(pdu, (uint8_t *)value, strlen(value)); 00639 00640 if (ret != CE_NONE) 00641 return EXO_GENERAL_ERROR; 00642 00643 return EXO_OK; 00644 } 00645 00646 exo_error exo_build_msg_rst(coap_pdu *pdu, const uint16_t mid, const uint64_t token, const uint8_t tkl) 00647 { 00648 coap_error ret; 00649 coap_init_pdu(pdu); 00650 ret = coap_set_version(pdu, COAP_V1); 00651 ret |= coap_set_type(pdu, CT_RST); 00652 ret |= coap_set_code(pdu, CC_EMPTY); 00653 ret |= coap_set_mid(pdu, mid); 00654 ret |= coap_set_token(pdu, token, tkl); 00655 00656 if (ret != CE_NONE) 00657 return EXO_GENERAL_ERROR; 00658 00659 return EXO_OK; 00660 } 00661 00662 exo_error exo_build_msg_ack(coap_pdu *pdu, const uint16_t mid) 00663 { 00664 coap_error ret; 00665 coap_init_pdu(pdu); 00666 ret = coap_set_version(pdu, COAP_V1); 00667 ret |= coap_set_type(pdu, CT_ACK); 00668 ret |= coap_set_code(pdu, CC_EMPTY); 00669 ret |= coap_set_mid(pdu, mid); 00670 00671 if (ret != CE_NONE) 00672 return EXO_GENERAL_ERROR; 00673 00674 return EXO_OK; 00675 } 00676 00677 exo_error exo_do_activate() 00678 { 00679 exo_op op; 00680 00681 exo_op_init(&op); 00682 00683 00684 return EXO_OK; 00685 } 00686 00687 uint8_t exo_util_is_ascii_hex(const char *str, size_t len) 00688 { 00689 size_t i; 00690 00691 for (i = 0; i < len; i++) { 00692 if (!((str[i] >= 'a' && str[i] <= 'f') || 00693 (str[i] >= '0' && str[i] <= '9'))) { 00694 return 1; 00695 } 00696 } 00697 00698 return 0; 00699 } 00700
Generated on Tue Jul 12 2022 18:09:07 by
1.7.2