Blame view
orbimote/firmware/loramac_utils.c
4.4 KB
ca223e024
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
/* * Copyright (C) 2020 INRIA * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level * directory for more details. */ /** * @ingroup pkg_semtech_loramac * @{ * * @file * @brief Utility functions for Semtech LoRaMac library. * * @author Didier Donsez <didier.donsez@univ-grenoble-alpes.fr> * * @} */ #include <stddef.h> #define ENABLE_DEBUG (1) #include "debug.h" #include "inttypes.h" #include "net/loramac.h" #include "semtech_loramac.h" #include <string.h> #include "cpu_conf.h" #include "periph/cpuid.h" #include "hashes/sha1.h" // TODO print_loramac(semtech_loramac_t *loramac) char *semtech_loramac_err_message(uint8_t errCode) { switch (errCode) { case SEMTECH_LORAMAC_JOIN_SUCCEEDED: return "Join procedure succeeded"; case SEMTECH_LORAMAC_JOIN_FAILED: return "Join procedure failed"; case SEMTECH_LORAMAC_NOT_JOINED: return "MAC is not joined"; case SEMTECH_LORAMAC_ALREADY_JOINED: return "MAC is already joined"; case SEMTECH_LORAMAC_TX_OK: return "Transmission is in progress"; case SEMTECH_LORAMAC_TX_SCHEDULE: return "TX needs reschedule"; case SEMTECH_LORAMAC_TX_DONE: return "Transmission completed"; case SEMTECH_LORAMAC_TX_CNF_FAILED: return "Confirmable transmission failed"; case SEMTECH_LORAMAC_TX_ERROR: return "Error in TX (invalid param, unknown service)"; case SEMTECH_LORAMAC_RX_DATA: return "Data received"; case SEMTECH_LORAMAC_RX_LINK_CHECK: return "Link check info received"; case SEMTECH_LORAMAC_RX_CONFIRMED: return "Confirmed ACK received"; case SEMTECH_LORAMAC_BUSY: return "Internal MAC is busy"; case SEMTECH_LORAMAC_DUTYCYCLE_RESTRICTED: return "Restricted access to channels"; default: return "Unknown reason"; } } /** * start the OTAA join procedure (and retries if required) */ uint8_t loramac_join_retry_loop(semtech_loramac_t *loramac, uint8_t initDataRate, uint32_t nextRetryTime, uint32_t maxNextRetryTime) { // TODO print DevEUI, AppEUI, AppKey DEBUG("Starting join procedure: dr=%d ", initDataRate); semtech_loramac_set_dr(loramac, initDataRate); uint8_t joinRes; while ((joinRes = semtech_loramac_join(loramac, LORAMAC_JOIN_OTAA)) != SEMTECH_LORAMAC_JOIN_SUCCEEDED) { DEBUG("Join procedure failed: code=%d (%s) ", joinRes, semtech_loramac_err_message(joinRes)); if (initDataRate > 0) { /* decrement Join initDataRate */ initDataRate--; semtech_loramac_set_dr(loramac, initDataRate); } else { /* double nextRetryTime in order to save the battery */ if (nextRetryTime < maxNextRetryTime) { nextRetryTime *= 2; } else { nextRetryTime = maxNextRetryTime; } } DEBUG("Retry join procedure in %ld sec. at dr=%d ", nextRetryTime, initDataRate); /* sleep JOIN_NEXT_TENTATIVE secs */ xtimer_sleep(nextRetryTime); } DEBUG("Join procedure succeeded "); return joinRes; } static const uint8_t appeui_mask[LORAMAC_APPEUI_LEN/2] = { 0xff, 0xff, 0xff, 0xff }; void printf_ba(const uint8_t* ba, size_t len) { for (unsigned int i = 0; i < len; i++) { DEBUG("%02x", ba[i]); } } /** * Forge the DevEUI, AppEUI and the AppKey from the CPU ID of the MCU and a secret array of bytes */ void loramac_forge_deveui(uint8_t *deveui, uint8_t *appeui, uint8_t *appkey, const uint8_t* secret) { uint8_t id[CPUID_LEN]; /* read the CPUID */ cpuid_get(id); if(CPUID_LEN > LORAMAC_DEVEUI_LEN) { memcpy(deveui,id+(CPUID_LEN-LORAMAC_DEVEUI_LEN),LORAMAC_DEVEUI_LEN); } else { memcpy(deveui+(LORAMAC_DEVEUI_LEN-CPUID_LEN),id,LORAMAC_DEVEUI_LEN); } memcpy(appeui,deveui,LORAMAC_APPEUI_LEN); memcpy(appeui+(LORAMAC_APPEUI_LEN/2),appeui_mask,LORAMAC_APPEUI_LEN/2); // Use secret for generating securely the appkey sha1_context ctx; sha1_init(&ctx); sha1_update(&ctx, deveui, LORAMAC_DEVEUI_LEN); sha1_update(&ctx, appeui, LORAMAC_APPEUI_LEN); sha1_update(&ctx, secret, LORAMAC_APPKEY_LEN); uint8_t digest[SHA1_DIGEST_LENGTH]; sha1_final(&ctx, &digest); memcpy(appkey,digest,LORAMAC_APPKEY_LEN); } |