mirror of
https://github.com/manuelbl/ttn-esp32.git
synced 2025-06-15 04:14:28 +02:00
Convert TTNProvisioning to C
This commit is contained in:
parent
99bab17d4b
commit
973a7c41c8
@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* ttn-esp32 - The Things Network device library for ESP-IDF / SX127x
|
* ttn-esp32 - The Things Network device library for ESP-IDF / SX127x
|
||||||
*
|
*
|
||||||
* Copyright (c) 2018-2019 Manuel Bleichenbacher
|
* Copyright (c) 2018-2021 Manuel Bleichenbacher
|
||||||
*
|
*
|
||||||
* Licensed under MIT License
|
* Licensed under MIT License
|
||||||
* https://opensource.org/licenses/MIT
|
* https://opensource.org/licenses/MIT
|
||||||
@ -13,60 +13,22 @@
|
|||||||
#ifndef _ttnprovisioning_h_
|
#ifndef _ttnprovisioning_h_
|
||||||
#define _ttnprovisioning_h_
|
#define _ttnprovisioning_h_
|
||||||
|
|
||||||
#include "lmic/oslmic.h"
|
#include "ttn_provisioning.h"
|
||||||
#include "nvs_flash.h"
|
|
||||||
|
|
||||||
|
|
||||||
class TTNProvisioning
|
class TTNProvisioning
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TTNProvisioning();
|
TTNProvisioning() { ttn_provision_init(); }
|
||||||
|
|
||||||
bool haveKeys();
|
bool haveKeys() { return ttn_provision_have_keys(); }
|
||||||
bool decodeKeys(const char *dev_eui, const char *app_eui, const char *app_key);
|
bool decodeKeys(const char *dev_eui, const char *app_eui, const char *app_key) { return ttn_provision_decode_keys(dev_eui, app_eui, app_key); }
|
||||||
bool fromMAC(const char *app_eui, const char *app_key);
|
bool fromMAC(const char *app_eui, const char *app_key) { return ttn_provision_from_mac(app_eui, app_key); }
|
||||||
bool saveKeys();
|
bool saveKeys() { return ttn_provision_save_keys(); }
|
||||||
bool restoreKeys(bool silent);
|
bool restoreKeys(bool silent) { return ttn_provision_restore_keys(silent); }
|
||||||
|
|
||||||
#if defined(TTN_HAS_AT_COMMANDS)
|
#if defined(TTN_HAS_AT_COMMANDS)
|
||||||
void startTask();
|
void startTask() { ttn_provision_start_task(); }
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool decode(bool incl_dev_eui, const char *dev_eui, const char *app_eui, const char *app_key);
|
|
||||||
bool readNvsValue(nvs_handle handle, const char* key, uint8_t* data, size_t expected_length, bool silent);
|
|
||||||
bool writeNvsValue(nvs_handle handle, const char* key, const uint8_t* data, size_t len);
|
|
||||||
|
|
||||||
#if defined(TTN_HAS_AT_COMMANDS)
|
|
||||||
void provisioningTask();
|
|
||||||
void addLineData(int numBytes);
|
|
||||||
void detectLineEnd(int start_at);
|
|
||||||
void processLine();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(TTN_CONFIG_UART)
|
|
||||||
void configUART();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool hexStrToBin(const char *hex, uint8_t *buf, int len);
|
|
||||||
static int hexTupleToByte(const char *hex);
|
|
||||||
static int hexDigitToVal(char ch);
|
|
||||||
static void binToHexStr(const uint8_t* buf, int len, char* hex);
|
|
||||||
static char valToHexDigit(int val);
|
|
||||||
static void swapBytes(uint8_t* buf, int len);
|
|
||||||
static bool isAllZeros(const uint8_t* buf, int len);
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool have_keys = false;
|
|
||||||
|
|
||||||
#if defined(TTN_HAS_AT_COMMANDS)
|
|
||||||
QueueHandle_t uart_queue;
|
|
||||||
char* line_buf;
|
|
||||||
int line_length;
|
|
||||||
uint8_t last_line_end_char;
|
|
||||||
bool quit_task;
|
|
||||||
|
|
||||||
friend void ttn_provisioning_task_caller(void* pvParameter);
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include "hal/hal_esp32.h"
|
#include "hal/hal_esp32.h"
|
||||||
#include "lmic/lmic.h"
|
#include "lmic/lmic.h"
|
||||||
#include "TheThingsNetwork.h"
|
#include "TheThingsNetwork.h"
|
||||||
#include "TTNProvisioning.h"
|
#include "ttn_provisioning.h"
|
||||||
#include "TTNLogging.h"
|
#include "TTNLogging.h"
|
||||||
|
|
||||||
|
|
||||||
@ -59,7 +59,6 @@ static const char *TAG = "ttn";
|
|||||||
static TheThingsNetwork* ttnInstance;
|
static TheThingsNetwork* ttnInstance;
|
||||||
static QueueHandle_t lmicEventQueue = nullptr;
|
static QueueHandle_t lmicEventQueue = nullptr;
|
||||||
static TTNWaitingReason waitingReason = eWaitingNone;
|
static TTNWaitingReason waitingReason = eWaitingNone;
|
||||||
static TTNProvisioning provisioning;
|
|
||||||
#if LMIC_ENABLE_event_logging
|
#if LMIC_ENABLE_event_logging
|
||||||
static TTNLogging* logging;
|
static TTNLogging* logging;
|
||||||
#endif
|
#endif
|
||||||
@ -138,25 +137,25 @@ void TheThingsNetwork::startup()
|
|||||||
|
|
||||||
bool TheThingsNetwork::provision(const char *devEui, const char *appEui, const char *appKey)
|
bool TheThingsNetwork::provision(const char *devEui, const char *appEui, const char *appKey)
|
||||||
{
|
{
|
||||||
if (!provisioning.decodeKeys(devEui, appEui, appKey))
|
if (!ttn_provision_decode_keys(devEui, appEui, appKey))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return provisioning.saveKeys();
|
return ttn_provision_save_keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TheThingsNetwork::provisionWithMAC(const char *appEui, const char *appKey)
|
bool TheThingsNetwork::provisionWithMAC(const char *appEui, const char *appKey)
|
||||||
{
|
{
|
||||||
if (!provisioning.fromMAC(appEui, appKey))
|
if (!ttn_provision_from_mac(appEui, appKey))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return provisioning.saveKeys();
|
return ttn_provision_save_keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TheThingsNetwork::startProvisioningTask()
|
void TheThingsNetwork::startProvisioningTask()
|
||||||
{
|
{
|
||||||
#if defined(TTN_HAS_AT_COMMANDS)
|
#if defined(TTN_HAS_AT_COMMANDS)
|
||||||
provisioning.startTask();
|
ttn_provision_start_task();
|
||||||
#else
|
#else
|
||||||
ESP_LOGE(TAG, "AT commands are disabled. Change the configuration using 'make menuconfig'");
|
ESP_LOGE(TAG, "AT commands are disabled. Change the configuration using 'make menuconfig'");
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
@ -173,7 +172,7 @@ void TheThingsNetwork::waitForProvisioning()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!provisioning.haveKeys())
|
while (!ttn_provision_have_keys())
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Device successfully provisioned");
|
ESP_LOGI(TAG, "Device successfully provisioned");
|
||||||
@ -186,7 +185,7 @@ void TheThingsNetwork::waitForProvisioning()
|
|||||||
|
|
||||||
bool TheThingsNetwork::join(const char *devEui, const char *appEui, const char *appKey)
|
bool TheThingsNetwork::join(const char *devEui, const char *appEui, const char *appKey)
|
||||||
{
|
{
|
||||||
if (!provisioning.decodeKeys(devEui, appEui, appKey))
|
if (!ttn_provision_decode_keys(devEui, appEui, appKey))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return joinCore();
|
return joinCore();
|
||||||
@ -194,9 +193,9 @@ bool TheThingsNetwork::join(const char *devEui, const char *appEui, const char *
|
|||||||
|
|
||||||
bool TheThingsNetwork::join()
|
bool TheThingsNetwork::join()
|
||||||
{
|
{
|
||||||
if (!provisioning.haveKeys())
|
if (!ttn_provision_have_keys())
|
||||||
{
|
{
|
||||||
if (!provisioning.restoreKeys(false))
|
if (!ttn_provision_restore_keys(false))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,7 +204,7 @@ bool TheThingsNetwork::join()
|
|||||||
|
|
||||||
bool TheThingsNetwork::joinCore()
|
bool TheThingsNetwork::joinCore()
|
||||||
{
|
{
|
||||||
if (!provisioning.haveKeys())
|
if (!ttn_provision_have_keys())
|
||||||
{
|
{
|
||||||
ESP_LOGW(TAG, "Device EUI, App EUI and/or App key have not been provided");
|
ESP_LOGW(TAG, "Device EUI, App EUI and/or App key have not been provided");
|
||||||
return false;
|
return false;
|
||||||
@ -271,12 +270,12 @@ void TheThingsNetwork::onMessage(TTNMessageCallback callback)
|
|||||||
|
|
||||||
bool TheThingsNetwork::isProvisioned()
|
bool TheThingsNetwork::isProvisioned()
|
||||||
{
|
{
|
||||||
if (provisioning.haveKeys())
|
if (ttn_provision_have_keys())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
provisioning.restoreKeys(true);
|
ttn_provision_restore_keys(true);
|
||||||
|
|
||||||
return provisioning.haveKeys();
|
return ttn_provision_have_keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TheThingsNetwork::setRSSICal(int8_t rssiCal)
|
void TheThingsNetwork::setRSSICal(int8_t rssiCal)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* ttn-esp32 - The Things Network device library for ESP-IDF / SX127x
|
* ttn-esp32 - The Things Network device library for ESP-IDF / SX127x
|
||||||
*
|
*
|
||||||
* Copyright (c) 2018-2019 Manuel Bleichenbacher
|
* Copyright (c) 2018-2021 Manuel Bleichenbacher
|
||||||
*
|
*
|
||||||
* Licensed under MIT License
|
* Licensed under MIT License
|
||||||
* https://opensource.org/licenses/MIT
|
* https://opensource.org/licenses/MIT
|
||||||
@ -10,34 +10,62 @@
|
|||||||
* Task listening on a UART port for provisioning commands.
|
* Task listening on a UART port for provisioning commands.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include "ttn_provisioning.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "driver/uart.h"
|
#include "driver/uart.h"
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "TTNProvisioning.h"
|
|
||||||
#include "lmic/lmic.h"
|
#include "lmic/lmic.h"
|
||||||
#include "hal/hal_esp32.h"
|
//#include "hal/hal_esp32.h"
|
||||||
|
|
||||||
#if defined(TTN_HAS_AT_COMMANDS)
|
#if defined(TTN_HAS_AT_COMMANDS)
|
||||||
const uart_port_t UART_NUM = (uart_port_t) CONFIG_TTN_PROVISION_UART_NUM;
|
#define UART_NUM CONFIG_TTN_PROVISION_UART_NUM
|
||||||
const int MAX_LINE_LENGTH = 128;
|
#define MAX_LINE_LENGTH 128
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char* const TAG = "ttn_prov";
|
#define TAG "ttn_prov"
|
||||||
static const char* const NVS_FLASH_PARTITION = "ttn";
|
#define NVS_FLASH_PARTITION "ttn"
|
||||||
static const char* const NVS_FLASH_KEY_DEV_EUI = "devEui";
|
#define NVS_FLASH_KEY_DEV_EUI "devEui"
|
||||||
static const char* const NVS_FLASH_KEY_APP_EUI = "appEui";
|
#define NVS_FLASH_KEY_APP_EUI "appEui"
|
||||||
static const char* const NVS_FLASH_KEY_APP_KEY = "appKey";
|
#define NVS_FLASH_KEY_APP_KEY "appKey"
|
||||||
|
|
||||||
|
#if defined(TTN_HAS_AT_COMMANDS)
|
||||||
|
static void provisioning_task(void* pvParameter);
|
||||||
|
static void add_line_data(int num_bytes);
|
||||||
|
static void detect_line_end(int start_at);
|
||||||
|
static void process_line(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TTN_CONFIG_UART)
|
||||||
|
static void config_uart(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool decode(bool incl_dev_eui, const char *dev_eui, const char *app_eui, const char *app_key);
|
||||||
|
static bool read_nvs_value(nvs_handle handle, const char* key, uint8_t* data, size_t expected_length, bool silent);
|
||||||
|
static bool write_nvs_value(nvs_handle handle, const char* key, const uint8_t* data, size_t len);
|
||||||
|
|
||||||
|
static bool hex_str_to_bin(const char *hex, uint8_t *buf, int len);
|
||||||
|
static int hex_tuple_to_byte(const char *hex);
|
||||||
|
static int hex_digit_to_val(char ch);
|
||||||
|
static void bin_to_hex_str(const uint8_t* buf, int len, char* hex);
|
||||||
|
static char val_to_hex_digit(int val);
|
||||||
|
static void swap_bytes(uint8_t* buf, int len);
|
||||||
|
static bool is_all_zeros(const uint8_t* buf, int len);
|
||||||
|
|
||||||
static uint8_t global_dev_eui[8];
|
static uint8_t global_dev_eui[8];
|
||||||
static uint8_t global_app_eui[8];
|
static uint8_t global_app_eui[8];
|
||||||
static uint8_t global_app_key[16];
|
static uint8_t global_app_key[16];
|
||||||
|
|
||||||
|
static bool have_keys = false;
|
||||||
|
|
||||||
#if defined(TTN_HAS_AT_COMMANDS)
|
#if defined(TTN_HAS_AT_COMMANDS)
|
||||||
void ttn_provisioning_task_caller(void* pvParameter);
|
static QueueHandle_t uart_queue;
|
||||||
|
static char* line_buf;
|
||||||
|
static int line_length;
|
||||||
|
static uint8_t last_line_end_char;
|
||||||
|
static bool quit_task;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -68,11 +96,7 @@ void os_getDevKey (u1_t* buf)
|
|||||||
|
|
||||||
// --- Constructor
|
// --- Constructor
|
||||||
|
|
||||||
TTNProvisioning::TTNProvisioning()
|
void ttn_provision_init(void)
|
||||||
: have_keys(false)
|
|
||||||
#if defined(TTN_HAS_AT_COMMANDS)
|
|
||||||
, uart_queue(nullptr), line_buf(nullptr), line_length(0), last_line_end_char(0), quit_task(false)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,26 +105,19 @@ TTNProvisioning::TTNProvisioning()
|
|||||||
|
|
||||||
#if defined(TTN_HAS_AT_COMMANDS)
|
#if defined(TTN_HAS_AT_COMMANDS)
|
||||||
|
|
||||||
void TTNProvisioning::startTask()
|
void ttn_provision_start_task(void)
|
||||||
{
|
{
|
||||||
#if defined(TTN_CONFIG_UART)
|
#if defined(TTN_CONFIG_UART)
|
||||||
configUART();
|
config_uart();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
esp_err_t err = uart_driver_install(UART_NUM, 2048, 2048, 20, &uart_queue, 0);
|
esp_err_t err = uart_driver_install(UART_NUM, 2048, 2048, 20, &uart_queue, 0);
|
||||||
ESP_ERROR_CHECK(err);
|
ESP_ERROR_CHECK(err);
|
||||||
|
|
||||||
xTaskCreate(ttn_provisioning_task_caller, "ttn_provision", 2048, this, 1, nullptr);
|
xTaskCreate(provisioning_task, "ttn_provision", 2048, NULL, 1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ttn_provisioning_task_caller(void* pvParameter)
|
void provisioning_task(void* pvParameter)
|
||||||
{
|
|
||||||
TTNProvisioning* provisioning = (TTNProvisioning*)pvParameter;
|
|
||||||
provisioning->provisioningTask();
|
|
||||||
vTaskDelete(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TTNProvisioning::provisioningTask()
|
|
||||||
{
|
{
|
||||||
line_buf = (char*)malloc(MAX_LINE_LENGTH + 1);
|
line_buf = (char*)malloc(MAX_LINE_LENGTH + 1);
|
||||||
line_length = 0;
|
line_length = 0;
|
||||||
@ -117,7 +134,7 @@ void TTNProvisioning::provisioningTask()
|
|||||||
switch (event.type)
|
switch (event.type)
|
||||||
{
|
{
|
||||||
case UART_DATA:
|
case UART_DATA:
|
||||||
addLineData(event.size);
|
add_line_data(event.size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UART_FIFO_OVF:
|
case UART_FIFO_OVF:
|
||||||
@ -133,13 +150,14 @@ void TTNProvisioning::provisioningTask()
|
|||||||
|
|
||||||
free(line_buf);
|
free(line_buf);
|
||||||
uart_driver_delete(UART_NUM);
|
uart_driver_delete(UART_NUM);
|
||||||
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTNProvisioning::addLineData(int numBytes)
|
void add_line_data(int num_bytes)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
top:
|
top:
|
||||||
n = numBytes;
|
n = num_bytes;
|
||||||
if (line_length + n > MAX_LINE_LENGTH)
|
if (line_length + n > MAX_LINE_LENGTH)
|
||||||
n = MAX_LINE_LENGTH - line_length;
|
n = MAX_LINE_LENGTH - line_length;
|
||||||
|
|
||||||
@ -147,16 +165,16 @@ top:
|
|||||||
int start_at = line_length;
|
int start_at = line_length;
|
||||||
line_length += n;
|
line_length += n;
|
||||||
|
|
||||||
detectLineEnd(start_at);
|
detect_line_end(start_at);
|
||||||
|
|
||||||
if (n < numBytes)
|
if (n < num_bytes)
|
||||||
{
|
{
|
||||||
numBytes -= n;
|
num_bytes -= n;
|
||||||
goto top;
|
goto top;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTNProvisioning::detectLineEnd(int start_at)
|
void detect_line_end(int start_at)
|
||||||
{
|
{
|
||||||
top:
|
top:
|
||||||
for (int p = start_at; p < line_length; p++)
|
for (int p = start_at; p < line_length; p++)
|
||||||
@ -173,7 +191,7 @@ top:
|
|||||||
last_line_end_char = ch;
|
last_line_end_char = ch;
|
||||||
|
|
||||||
if (p > 0)
|
if (p > 0)
|
||||||
processLine();
|
process_line();
|
||||||
|
|
||||||
memcpy(line_buf, line_buf + p + 1, line_length - p - 1);
|
memcpy(line_buf, line_buf + p + 1, line_length - p - 1);
|
||||||
line_length -= p + 1;
|
line_length -= p + 1;
|
||||||
@ -189,7 +207,7 @@ top:
|
|||||||
line_length = 0; // Line too long; flush it
|
line_length = 0; // Line too long; flush it
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTNProvisioning::processLine()
|
void process_line(void)
|
||||||
{
|
{
|
||||||
bool is_ok = true;
|
bool is_ok = true;
|
||||||
bool reset_needed = false;
|
bool reset_needed = false;
|
||||||
@ -207,14 +225,14 @@ void TTNProvisioning::processLine()
|
|||||||
char hexbuf[16];
|
char hexbuf[16];
|
||||||
|
|
||||||
memcpy(binbuf, global_dev_eui, 8);
|
memcpy(binbuf, global_dev_eui, 8);
|
||||||
swapBytes(binbuf, 8);
|
swap_bytes(binbuf, 8);
|
||||||
binToHexStr(binbuf, 8, hexbuf);
|
bin_to_hex_str(binbuf, 8, hexbuf);
|
||||||
uart_write_bytes(UART_NUM, hexbuf, 16);
|
uart_write_bytes(UART_NUM, hexbuf, 16);
|
||||||
uart_write_bytes(UART_NUM, "-", 1);
|
uart_write_bytes(UART_NUM, "-", 1);
|
||||||
|
|
||||||
memcpy(binbuf, global_app_eui, 8);
|
memcpy(binbuf, global_app_eui, 8);
|
||||||
swapBytes(binbuf, 8);
|
swap_bytes(binbuf, 8);
|
||||||
binToHexStr(binbuf, 8, hexbuf);
|
bin_to_hex_str(binbuf, 8, hexbuf);
|
||||||
uart_write_bytes(UART_NUM, hexbuf, 16);
|
uart_write_bytes(UART_NUM, hexbuf, 16);
|
||||||
|
|
||||||
uart_write_bytes(UART_NUM, "-00000000000000000000000000000000\r\n", 35);
|
uart_write_bytes(UART_NUM, "-00000000000000000000000000000000\r\n", 35);
|
||||||
@ -226,9 +244,9 @@ void TTNProvisioning::processLine()
|
|||||||
{
|
{
|
||||||
line_buf[24] = 0;
|
line_buf[24] = 0;
|
||||||
line_buf[41] = 0;
|
line_buf[41] = 0;
|
||||||
is_ok = decodeKeys(line_buf + 8, line_buf + 25, line_buf + 42);
|
is_ok = ttn_provision_decode_keys(line_buf + 8, line_buf + 25, line_buf + 42);
|
||||||
if (is_ok)
|
if (is_ok)
|
||||||
is_ok = saveKeys();
|
is_ok = ttn_provision_save_keys();
|
||||||
reset_needed = is_ok;
|
reset_needed = is_ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,9 +256,9 @@ void TTNProvisioning::processLine()
|
|||||||
if (is_ok)
|
if (is_ok)
|
||||||
{
|
{
|
||||||
line_buf[25] = 0;
|
line_buf[25] = 0;
|
||||||
is_ok = fromMAC(line_buf + 9, line_buf + 26);
|
is_ok = ttn_provision_from_mac(line_buf + 9, line_buf + 26);
|
||||||
if (is_ok)
|
if (is_ok)
|
||||||
is_ok = saveKeys();
|
is_ok = ttn_provision_save_keys();
|
||||||
reset_needed = is_ok;
|
reset_needed = is_ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,7 +270,7 @@ void TTNProvisioning::processLine()
|
|||||||
esp_err_t err = esp_efuse_mac_get_default(mac);
|
esp_err_t err = esp_efuse_mac_get_default(mac);
|
||||||
ESP_ERROR_CHECK(err);
|
ESP_ERROR_CHECK(err);
|
||||||
|
|
||||||
binToHexStr(mac, 6, hexbuf);
|
bin_to_hex_str(mac, 6, hexbuf);
|
||||||
for (int i = 0; i < 12; i += 2) {
|
for (int i = 0; i < 12; i += 2) {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
uart_write_bytes(UART_NUM, ":", 1);
|
uart_write_bytes(UART_NUM, ":", 1);
|
||||||
@ -268,7 +286,7 @@ void TTNProvisioning::processLine()
|
|||||||
esp_err_t err = esp_efuse_mac_get_default(mac);
|
esp_err_t err = esp_efuse_mac_get_default(mac);
|
||||||
ESP_ERROR_CHECK(err);
|
ESP_ERROR_CHECK(err);
|
||||||
|
|
||||||
binToHexStr(mac, 6, hexbuf);
|
bin_to_hex_str(mac, 6, hexbuf);
|
||||||
for (int i = 0; i < 12; i += 2) {
|
for (int i = 0; i < 12; i += 2) {
|
||||||
uart_write_bytes(UART_NUM, hexbuf + i, 2);
|
uart_write_bytes(UART_NUM, hexbuf + i, 2);
|
||||||
if (i == 4)
|
if (i == 4)
|
||||||
@ -287,9 +305,10 @@ void TTNProvisioning::processLine()
|
|||||||
|
|
||||||
if (reset_needed)
|
if (reset_needed)
|
||||||
{
|
{
|
||||||
ttn_hal.enterCriticalSection();
|
// TODO
|
||||||
|
// ttn_hal.enterCriticalSection();
|
||||||
LMIC_reset();
|
LMIC_reset();
|
||||||
ttn_hal.leaveCriticalSection();
|
// ttn_hal.leaveCriticalSection();
|
||||||
LMIC.client.eventCb(LMIC.client.eventUserData, EV_RESET);
|
LMIC.client.eventCb(LMIC.client.eventUserData, EV_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +320,7 @@ void TTNProvisioning::processLine()
|
|||||||
|
|
||||||
#if defined(TTN_CONFIG_UART)
|
#if defined(TTN_CONFIG_UART)
|
||||||
|
|
||||||
void TTNProvisioning::configUART()
|
void config_uart(void)
|
||||||
{
|
{
|
||||||
esp_err_t err;
|
esp_err_t err;
|
||||||
|
|
||||||
@ -310,9 +329,7 @@ void TTNProvisioning::configUART()
|
|||||||
.data_bits = UART_DATA_8_BITS,
|
.data_bits = UART_DATA_8_BITS,
|
||||||
.parity = UART_PARITY_DISABLE,
|
.parity = UART_PARITY_DISABLE,
|
||||||
.stop_bits = UART_STOP_BITS_1,
|
.stop_bits = UART_STOP_BITS_1,
|
||||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
|
||||||
.rx_flow_ctrl_thresh = 0,
|
|
||||||
.use_ref_tick = false
|
|
||||||
};
|
};
|
||||||
err = uart_param_config(UART_NUM, &uart_config);
|
err = uart_param_config(UART_NUM, &uart_config);
|
||||||
ESP_ERROR_CHECK(err);
|
ESP_ERROR_CHECK(err);
|
||||||
@ -326,17 +343,17 @@ void TTNProvisioning::configUART()
|
|||||||
|
|
||||||
// --- Key handling
|
// --- Key handling
|
||||||
|
|
||||||
bool TTNProvisioning::haveKeys()
|
bool ttn_provision_have_keys(void)
|
||||||
{
|
{
|
||||||
return have_keys;
|
return have_keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TTNProvisioning::decodeKeys(const char *dev_eui, const char *app_eui, const char *app_key)
|
bool ttn_provision_decode_keys(const char *dev_eui, const char *app_eui, const char *app_key)
|
||||||
{
|
{
|
||||||
return decode(true, dev_eui, app_eui, app_key);
|
return decode(true, dev_eui, app_eui, app_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TTNProvisioning::fromMAC(const char *app_eui, const char *app_key)
|
bool ttn_provision_from_mac(const char *app_eui, const char *app_key)
|
||||||
{
|
{
|
||||||
uint8_t mac[6];
|
uint8_t mac[6];
|
||||||
esp_err_t err = esp_efuse_mac_get_default(mac);
|
esp_err_t err = esp_efuse_mac_get_default(mac);
|
||||||
@ -351,33 +368,33 @@ bool TTNProvisioning::fromMAC(const char *app_eui, const char *app_key)
|
|||||||
global_dev_eui[1] = mac[4];
|
global_dev_eui[1] = mac[4];
|
||||||
global_dev_eui[0] = mac[5];
|
global_dev_eui[0] = mac[5];
|
||||||
|
|
||||||
return decode(false, nullptr, app_eui, app_key);
|
return decode(false, NULL, app_eui, app_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TTNProvisioning::decode(bool incl_dev_eui, const char *dev_eui, const char *app_eui, const char *app_key)
|
bool decode(bool incl_dev_eui, const char *dev_eui, const char *app_eui, const char *app_key)
|
||||||
{
|
{
|
||||||
uint8_t buf_dev_eui[8];
|
uint8_t buf_dev_eui[8];
|
||||||
uint8_t buf_app_eui[8];
|
uint8_t buf_app_eui[8];
|
||||||
uint8_t buf_app_key[16];
|
uint8_t buf_app_key[16];
|
||||||
|
|
||||||
if (incl_dev_eui && (strlen(dev_eui) != 16 || !hexStrToBin(dev_eui, buf_dev_eui, 8)))
|
if (incl_dev_eui && (strlen(dev_eui) != 16 || !hex_str_to_bin(dev_eui, buf_dev_eui, 8)))
|
||||||
{
|
{
|
||||||
ESP_LOGW(TAG, "Invalid device EUI: %s", dev_eui);
|
ESP_LOGW(TAG, "Invalid device EUI: %s", dev_eui);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (incl_dev_eui)
|
if (incl_dev_eui)
|
||||||
swapBytes(buf_dev_eui, 8);
|
swap_bytes(buf_dev_eui, 8);
|
||||||
|
|
||||||
if (strlen(app_eui) != 16 || !hexStrToBin(app_eui, buf_app_eui, 8))
|
if (strlen(app_eui) != 16 || !hex_str_to_bin(app_eui, buf_app_eui, 8))
|
||||||
{
|
{
|
||||||
ESP_LOGW(TAG, "Invalid application EUI: %s", app_eui);
|
ESP_LOGW(TAG, "Invalid application EUI: %s", app_eui);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
swapBytes(buf_app_eui, 8);
|
swap_bytes(buf_app_eui, 8);
|
||||||
|
|
||||||
if (strlen(app_key) != 32 || !hexStrToBin(app_key, buf_app_key, 16))
|
if (strlen(app_key) != 32 || !hex_str_to_bin(app_key, buf_app_key, 16))
|
||||||
{
|
{
|
||||||
ESP_LOGW(TAG, "Invalid application key: %s", app_key);
|
ESP_LOGW(TAG, "Invalid application key: %s", app_key);
|
||||||
return false;
|
return false;
|
||||||
@ -388,9 +405,9 @@ bool TTNProvisioning::decode(bool incl_dev_eui, const char *dev_eui, const char
|
|||||||
memcpy(global_app_eui, buf_app_eui, sizeof(global_app_eui));
|
memcpy(global_app_eui, buf_app_eui, sizeof(global_app_eui));
|
||||||
memcpy(global_app_key, buf_app_key, sizeof(global_app_key));
|
memcpy(global_app_key, buf_app_key, sizeof(global_app_key));
|
||||||
|
|
||||||
have_keys = !isAllZeros(global_dev_eui, sizeof(global_dev_eui))
|
have_keys = !is_all_zeros(global_dev_eui, sizeof(global_dev_eui))
|
||||||
&& !isAllZeros(global_app_eui, sizeof(global_app_eui))
|
&& !is_all_zeros(global_app_eui, sizeof(global_app_eui))
|
||||||
&& !isAllZeros(global_app_key, sizeof(global_app_key));
|
&& !is_all_zeros(global_app_key, sizeof(global_app_key));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -398,7 +415,7 @@ bool TTNProvisioning::decode(bool incl_dev_eui, const char *dev_eui, const char
|
|||||||
|
|
||||||
// --- Non-volatile storage
|
// --- Non-volatile storage
|
||||||
|
|
||||||
bool TTNProvisioning::saveKeys()
|
bool ttn_provision_save_keys()
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
@ -413,13 +430,13 @@ bool TTNProvisioning::saveKeys()
|
|||||||
if (res != ESP_OK)
|
if (res != ESP_OK)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (!writeNvsValue(handle, NVS_FLASH_KEY_DEV_EUI, global_dev_eui, sizeof(global_dev_eui)))
|
if (!write_nvs_value(handle, NVS_FLASH_KEY_DEV_EUI, global_dev_eui, sizeof(global_dev_eui)))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (!writeNvsValue(handle, NVS_FLASH_KEY_APP_EUI, global_app_eui, sizeof(global_app_eui)))
|
if (!write_nvs_value(handle, NVS_FLASH_KEY_APP_EUI, global_app_eui, sizeof(global_app_eui)))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (!writeNvsValue(handle, NVS_FLASH_KEY_APP_KEY, global_app_key, sizeof(global_app_key)))
|
if (!write_nvs_value(handle, NVS_FLASH_KEY_APP_KEY, global_app_key, sizeof(global_app_key)))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
res = nvs_commit(handle);
|
res = nvs_commit(handle);
|
||||||
@ -433,7 +450,7 @@ done:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TTNProvisioning::restoreKeys(bool silent)
|
bool ttn_provision_restore_keys(bool silent)
|
||||||
{
|
{
|
||||||
uint8_t buf_dev_eui[8];
|
uint8_t buf_dev_eui[8];
|
||||||
uint8_t buf_app_eui[8];
|
uint8_t buf_app_eui[8];
|
||||||
@ -452,22 +469,22 @@ bool TTNProvisioning::restoreKeys(bool silent)
|
|||||||
if (res != ESP_OK)
|
if (res != ESP_OK)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (!readNvsValue(handle, NVS_FLASH_KEY_DEV_EUI, buf_dev_eui, sizeof(global_dev_eui), silent))
|
if (!read_nvs_value(handle, NVS_FLASH_KEY_DEV_EUI, buf_dev_eui, sizeof(global_dev_eui), silent))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (!readNvsValue(handle, NVS_FLASH_KEY_APP_EUI, buf_app_eui, sizeof(global_app_eui), silent))
|
if (!read_nvs_value(handle, NVS_FLASH_KEY_APP_EUI, buf_app_eui, sizeof(global_app_eui), silent))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (!readNvsValue(handle, NVS_FLASH_KEY_APP_KEY, buf_app_key, sizeof(global_app_key), silent))
|
if (!read_nvs_value(handle, NVS_FLASH_KEY_APP_KEY, buf_app_key, sizeof(global_app_key), silent))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
memcpy(global_dev_eui, buf_dev_eui, sizeof(global_dev_eui));
|
memcpy(global_dev_eui, buf_dev_eui, sizeof(global_dev_eui));
|
||||||
memcpy(global_app_eui, buf_app_eui, sizeof(global_app_eui));
|
memcpy(global_app_eui, buf_app_eui, sizeof(global_app_eui));
|
||||||
memcpy(global_app_key, buf_app_key, sizeof(global_app_key));
|
memcpy(global_app_key, buf_app_key, sizeof(global_app_key));
|
||||||
|
|
||||||
have_keys = !isAllZeros(global_dev_eui, sizeof(global_dev_eui))
|
have_keys = !is_all_zeros(global_dev_eui, sizeof(global_dev_eui))
|
||||||
&& !isAllZeros(global_app_eui, sizeof(global_app_eui))
|
&& !is_all_zeros(global_app_eui, sizeof(global_app_eui))
|
||||||
&& !isAllZeros(global_app_key, sizeof(global_app_key));
|
&& !is_all_zeros(global_app_key, sizeof(global_app_key));
|
||||||
|
|
||||||
if (have_keys)
|
if (have_keys)
|
||||||
{
|
{
|
||||||
@ -483,7 +500,7 @@ done:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TTNProvisioning::readNvsValue(nvs_handle handle, const char* key, uint8_t* data, size_t expected_length, bool silent)
|
bool read_nvs_value(nvs_handle handle, const char* key, uint8_t* data, size_t expected_length, bool silent)
|
||||||
{
|
{
|
||||||
size_t size = expected_length;
|
size_t size = expected_length;
|
||||||
esp_err_t res = nvs_get_blob(handle, key, data, &size);
|
esp_err_t res = nvs_get_blob(handle, key, data, &size);
|
||||||
@ -508,10 +525,10 @@ bool TTNProvisioning::readNvsValue(nvs_handle handle, const char* key, uint8_t*
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TTNProvisioning::writeNvsValue(nvs_handle handle, const char* key, const uint8_t* data, size_t len)
|
bool write_nvs_value(nvs_handle handle, const char* key, const uint8_t* data, size_t len)
|
||||||
{
|
{
|
||||||
uint8_t buf[16];
|
uint8_t buf[16];
|
||||||
if (readNvsValue(handle, key, buf, len, true) && memcmp(buf, data, len) == 0)
|
if (read_nvs_value(handle, key, buf, len, true) && memcmp(buf, data, len) == 0)
|
||||||
return true; // unchanged
|
return true; // unchanged
|
||||||
|
|
||||||
esp_err_t res = nvs_set_blob(handle, key, data, len);
|
esp_err_t res = nvs_set_blob(handle, key, data, len);
|
||||||
@ -523,12 +540,12 @@ bool TTNProvisioning::writeNvsValue(nvs_handle handle, const char* key, const ui
|
|||||||
|
|
||||||
// --- Helper functions ---
|
// --- Helper functions ---
|
||||||
|
|
||||||
bool TTNProvisioning::hexStrToBin(const char *hex, uint8_t *buf, int len)
|
bool hex_str_to_bin(const char *hex, uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
const char* ptr = hex;
|
const char* ptr = hex;
|
||||||
for (int i = 0; i < len; i++)
|
for (int i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
int val = hexTupleToByte(ptr);
|
int val = hex_tuple_to_byte(ptr);
|
||||||
if (val < 0)
|
if (val < 0)
|
||||||
return false;
|
return false;
|
||||||
buf[i] = val;
|
buf[i] = val;
|
||||||
@ -537,18 +554,18 @@ bool TTNProvisioning::hexStrToBin(const char *hex, uint8_t *buf, int len)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TTNProvisioning::hexTupleToByte(const char *hex)
|
int hex_tuple_to_byte(const char *hex)
|
||||||
{
|
{
|
||||||
int nibble1 = hexDigitToVal(hex[0]);
|
int nibble1 = hex_digit_to_val(hex[0]);
|
||||||
if (nibble1 < 0)
|
if (nibble1 < 0)
|
||||||
return -1;
|
return -1;
|
||||||
int nibble2 = hexDigitToVal(hex[1]);
|
int nibble2 = hex_digit_to_val(hex[1]);
|
||||||
if (nibble2 < 0)
|
if (nibble2 < 0)
|
||||||
return -1;
|
return -1;
|
||||||
return (nibble1 << 4) | nibble2;
|
return (nibble1 << 4) | nibble2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TTNProvisioning::hexDigitToVal(char ch)
|
int hex_digit_to_val(char ch)
|
||||||
{
|
{
|
||||||
if (ch >= '0' && ch <= '9')
|
if (ch >= '0' && ch <= '9')
|
||||||
return ch - '0';
|
return ch - '0';
|
||||||
@ -559,24 +576,24 @@ int TTNProvisioning::hexDigitToVal(char ch)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTNProvisioning::binToHexStr(const uint8_t* buf, int len, char* hex)
|
void bin_to_hex_str(const uint8_t* buf, int len, char* hex)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < len; i++)
|
for (int i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
uint8_t b = buf[i];
|
uint8_t b = buf[i];
|
||||||
*hex = valToHexDigit((b & 0xf0) >> 4);
|
*hex = val_to_hex_digit((b & 0xf0) >> 4);
|
||||||
hex++;
|
hex++;
|
||||||
*hex = valToHexDigit(b & 0x0f);
|
*hex = val_to_hex_digit(b & 0x0f);
|
||||||
hex++;
|
hex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char TTNProvisioning::valToHexDigit(int val)
|
char val_to_hex_digit(int val)
|
||||||
{
|
{
|
||||||
return "0123456789ABCDEF"[val];
|
return "0123456789ABCDEF"[val];
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTNProvisioning::swapBytes(uint8_t* buf, int len)
|
void swap_bytes(uint8_t* buf, int len)
|
||||||
{
|
{
|
||||||
uint8_t* p1 = buf;
|
uint8_t* p1 = buf;
|
||||||
uint8_t* p2 = buf + len - 1;
|
uint8_t* p2 = buf + len - 1;
|
||||||
@ -590,7 +607,7 @@ void TTNProvisioning::swapBytes(uint8_t* buf, int len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TTNProvisioning::isAllZeros(const uint8_t* buf, int len)
|
bool is_all_zeros(const uint8_t* buf, int len)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < len; i++)
|
for (int i = 0; i < len; i++)
|
||||||
if (buf[i] != 0)
|
if (buf[i] != 0)
|
39
src/ttn_provisioning.h
Normal file
39
src/ttn_provisioning.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* ttn-esp32 - The Things Network device library for ESP-IDF / SX127x
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018-2021 Manuel Bleichenbacher
|
||||||
|
*
|
||||||
|
* Licensed under MIT License
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*
|
||||||
|
* Task listening on a UART port for provisioning commands.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TTN_PROVISIONING_H
|
||||||
|
#define TTN_PROVISIONING_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void ttn_provision_init(void);
|
||||||
|
|
||||||
|
|
||||||
|
bool ttn_provision_have_keys(void);
|
||||||
|
bool ttn_provision_decode_keys(const char *dev_eui, const char *app_eui, const char *app_key);
|
||||||
|
bool ttn_provision_from_mac(const char *app_eui, const char *app_key);
|
||||||
|
bool ttn_provision_save_keys(void);
|
||||||
|
bool ttn_provision_restore_keys(bool silent);
|
||||||
|
|
||||||
|
#if defined(TTN_HAS_AT_COMMANDS)
|
||||||
|
void ttn_provision_start_task(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user