Store app/dev EUI/key in NVS

This commit is contained in:
Manuel Bleichenbacher
2018-07-20 21:19:53 +02:00
parent fc34fed6de
commit 2c998f5acc
7 changed files with 218 additions and 36 deletions

View File

@ -11,6 +11,7 @@
#include "freertos/FreeRTOS.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include "TheThingsNetwork.h"
#include "esp_log.h"
#include "oslmic.h"
@ -26,6 +27,10 @@ enum ClientAction
};
static const char *TAG = "ttn";
static const char *NVS_FLASH_PARTITION = "ttn";
static const char *NVS_FLASH_KEY_DEV_EUI = "devEui";
static const char *NVS_FLASH_KEY_APP_EUI = "appEui";
static const char *NVS_FLASH_KEY_APP_KEY = "appKey";
static TheThingsNetwork* ttnInstance;
static uint8_t devEui[8];
@ -35,6 +40,8 @@ static QueueHandle_t resultQueue;
static ClientAction clientAction = eActionUnrelated;
static bool readNvsValue(nvs_handle handle, const char* key, uint8_t* data, size_t expectedLength, bool silent);
static bool writeNvsValue(nvs_handle handle, const char* key, const uint8_t* data, size_t len);
static bool hexStringToBin(const char *hex, uint8_t *buf, int len);
static int hexTupleToByte(const char *hex);
static int hexDigitToVal(char ch);
@ -42,6 +49,7 @@ static void swapByteOrder(uint8_t* buf, int len);
TheThingsNetwork::TheThingsNetwork()
: messageCallback(NULL), haveKeys(false)
{
ASSERT(ttnInstance == NULL);
ttnInstance = this;
@ -67,7 +75,7 @@ void TheThingsNetwork::configurePins(spi_host_device_t spi_host, uint8_t nss, ui
reset();
resultQueue = xQueueCreate(12, sizeof(int));
assert(resultQueue != NULL);
ASSERT(resultQueue != NULL);
hal_startBgTask();
}
@ -80,11 +88,16 @@ void TheThingsNetwork::reset()
bool TheThingsNetwork::provision(const char *devEui, const char *appEui, const char *appKey)
{
return decodeKeys(devEui, appEui, appKey);
if (!decodeKeys(devEui, appEui, appKey))
return false;
return saveKeys();
}
bool TheThingsNetwork::decodeKeys(const char *devEui, const char *appEui, const char *appKey)
{
haveKeys = false;
if (strlen(devEui) != 16 || !hexStringToBin(devEui, ::devEui, 8))
{
ESP_LOGW(TAG, "Invalid device EUI: %s", devEui);
@ -107,6 +120,7 @@ bool TheThingsNetwork::decodeKeys(const char *devEui, const char *appEui, const
return false;
}
haveKeys = true;
return true;
}
@ -115,11 +129,28 @@ bool TheThingsNetwork::join(const char *devEui, const char *appEui, const char *
if (!decodeKeys(devEui, appEui, appKey))
return false;
return join();
return joinCore();
}
bool TheThingsNetwork::join()
{
if (!haveKeys)
{
if (!restoreKeys(false))
return false;
}
return joinCore();
}
bool TheThingsNetwork::joinCore()
{
if (!haveKeys)
{
ESP_LOGW(TAG, "Device EUI, App EUI and/or App key have not been provided");
return false;
}
hal_enterCriticalSection();
clientAction = eActionJoining;
LMIC_startJoining();
@ -173,6 +204,120 @@ void TheThingsNetwork::onMessage(TTNMessageCallback callback)
messageCallback = callback;
}
bool TheThingsNetwork::saveKeys()
{
bool result = false;
nvs_handle handle = 0;
esp_err_t res = nvs_open(NVS_FLASH_PARTITION, NVS_READWRITE, &handle);
if (res == ESP_ERR_NVS_NOT_INITIALIZED)
{
ESP_LOGW(TAG, "NVS storage is not initialized. Call 'nvs_flash_init()' first.");
goto done;
}
ESP_ERROR_CHECK(res);
if (res != ESP_OK)
goto done;
if (!writeNvsValue(handle, NVS_FLASH_KEY_DEV_EUI, ::devEui, sizeof(::devEui)))
goto done;
if (!writeNvsValue(handle, NVS_FLASH_KEY_APP_EUI, ::appEui, sizeof(::appEui)))
goto done;
if (!writeNvsValue(handle, NVS_FLASH_KEY_APP_KEY, ::appKey, sizeof(::appKey)))
goto done;
res = nvs_commit(handle);
ESP_ERROR_CHECK(res);
result = true;
ESP_LOGI(TAG, "Dev and app EUI and app key saved in NVS storage");
done:
nvs_close(handle);
return result;
}
bool TheThingsNetwork::restoreKeys(bool silent)
{
haveKeys = false;
nvs_handle handle = 0;
esp_err_t res = nvs_open(NVS_FLASH_PARTITION, NVS_READONLY, &handle);
if (res == ESP_ERR_NVS_NOT_FOUND)
return false; // partition does not exist yet
if (res == ESP_ERR_NVS_NOT_INITIALIZED)
{
ESP_LOGW(TAG, "NVS storage is not initialized. Call 'nvs_flash_init()' first.");
goto done;
}
ESP_ERROR_CHECK(res);
if (res != ESP_OK)
goto done;
if (!readNvsValue(handle, NVS_FLASH_KEY_DEV_EUI, ::devEui, sizeof(::devEui), silent))
goto done;
if (!readNvsValue(handle, NVS_FLASH_KEY_APP_EUI, ::appEui, sizeof(::appEui), silent))
goto done;
if (!readNvsValue(handle, NVS_FLASH_KEY_APP_KEY, ::appKey, sizeof(::appKey), silent))
goto done;
haveKeys = true;
ESP_LOGI(TAG, "Dev and app EUI and app key have been restored from NVS storage");
done:
nvs_close(handle);
return haveKeys;
}
bool TheThingsNetwork::isProvisioned()
{
if (haveKeys)
return true;
return restoreKeys(true);
}
bool readNvsValue(nvs_handle handle, const char* key, uint8_t* data, size_t expectedLength, bool silent)
{
size_t size = expectedLength;
esp_err_t res = nvs_get_blob(handle, key, data, &size);
if (res == ESP_OK && size == expectedLength)
return true;
if (res == ESP_OK && size != expectedLength)
{
if (!silent)
ESP_LOGW(TAG, "Invalid size of NVS data for %s", key);
return false;
}
if (res == ESP_ERR_NVS_NOT_FOUND)
{
if (!silent)
ESP_LOGW(TAG, "No NVS data found for %s", key);
return false;
}
ESP_ERROR_CHECK(res);
return false;
}
bool writeNvsValue(nvs_handle handle, const char* key, const uint8_t* data, size_t len)
{
uint8_t buf[16];
if (readNvsValue(handle, key, buf, len, true) && memcmp(buf, data, len) == 0)
return true; // unchanged
esp_err_t res = nvs_set_blob(handle, key, data, len);
ESP_ERROR_CHECK(res);
return res == ESP_OK;
}
// --- LMIC functions ---

View File

@ -84,7 +84,7 @@ static void hal_io_init()
}
dio_queue = xQueueCreate(12, sizeof(queue_item_t));
assert(dio_queue != NULL);
ASSERT(dio_queue != NULL);
gpio_pad_select_gpio(lmic_pins.dio0);
gpio_set_direction(lmic_pins.dio0, GPIO_MODE_INPUT);
@ -151,8 +151,8 @@ static void collect_spi_result()
spi_transaction_t* trx;
esp_err_t err = spi_device_get_trans_result(spi_handle, &trx, 100 / portTICK_PERIOD_MS);
assert(err == ESP_OK);
assert(trx == spi_trx_queue + tail);
ESP_ERROR_CHECK(err);
ASSERT(trx == spi_trx_queue + tail);
spi_num_outstanding_trx--;
}
@ -163,7 +163,7 @@ static void submit_spi_trx()
int head = spi_trx_queue_head;
esp_err_t err = spi_device_queue_trans(spi_handle, spi_trx_queue + head, 100 / portTICK_PERIOD_MS);
assert(err == ESP_OK);
ESP_ERROR_CHECK(err);
spi_num_outstanding_trx++;
head++;
@ -185,7 +185,7 @@ static void hal_spi_init()
};
esp_err_t ret = spi_bus_add_device(lmic_pins.spi_host, &spi_device_intf_config, &spi_handle);
assert(ret == ESP_OK);
ESP_ERROR_CHECK(ret);
ESP_LOGI(TAG, "SPI initialized");
}
@ -459,5 +459,5 @@ void hal_startBgTask() {
void hal_failed(const char *file, u2_t line)
{
ESP_LOGE(TAG, "%s:%d", file, line);
assert(0);
ASSERT(0);
}