mirror of
				https://github.com/manuelbl/ttn-esp32.git
				synced 2025-10-31 18:50:33 +01:00 
			
		
		
		
	Store app/dev EUI/key in NVS
This commit is contained in:
		
							
								
								
									
										1
									
								
								.vscode/c_cpp_properties.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.vscode/c_cpp_properties.json
									
									
									
									
										vendored
									
									
								
							| @ -12,6 +12,7 @@ | |||||||
|                 "${IDF_PATH}/components/log/include", |                 "${IDF_PATH}/components/log/include", | ||||||
|                 "${IDF_PATH}/components/lwip/include/lwip", |                 "${IDF_PATH}/components/lwip/include/lwip", | ||||||
|                 "${IDF_PATH}/components/lwip/include/lwip/port", |                 "${IDF_PATH}/components/lwip/include/lwip/port", | ||||||
|  |                 "${IDF_PATH}/components/nvs_flash/include", | ||||||
|                 "${IDF_PATH}/components/soc/include", |                 "${IDF_PATH}/components/soc/include", | ||||||
|                 "${IDF_PATH}/components/soc/esp32/include", |                 "${IDF_PATH}/components/soc/esp32/include", | ||||||
|                 "${IDF_PATH}/components/tcpip_adapter/include", |                 "${IDF_PATH}/components/tcpip_adapter/include", | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ | |||||||
|  |  | ||||||
| #include "freertos/FreeRTOS.h" | #include "freertos/FreeRTOS.h" | ||||||
| #include "esp_event.h" | #include "esp_event.h" | ||||||
|  | #include "nvs_flash.h" | ||||||
|  |  | ||||||
| #include "TheThingsNetwork.h" | #include "TheThingsNetwork.h" | ||||||
|  |  | ||||||
| @ -33,15 +34,12 @@ const unsigned TX_INTERVAL = 30; | |||||||
| static uint8_t msgData[] = "Hello, world"; | static uint8_t msgData[] = "Hello, world"; | ||||||
|  |  | ||||||
|  |  | ||||||
| void send_messages(void* pvParameter) | void sendMessages(void* pvParameter) | ||||||
| { | { | ||||||
|     while (1) { |     while (1) { | ||||||
|         printf("Sending message...\n"); |         printf("Sending message...\n"); | ||||||
|         TTNResponseCode res = ttn.transmitBytes(msgData, sizeof(msgData) - 1); |         TTNResponseCode res = ttn.transmitBytes(msgData, sizeof(msgData) - 1); | ||||||
|         if (res == kTTNSuccessfulTransmission) |         printf(res == kTTNSuccessfulTransmission ? "Message sent.\n" : "Transmission failed.\n"); | ||||||
|             printf("Message sent.\n"); |  | ||||||
|         else |  | ||||||
|             printf("Transmission failed.\n"); |  | ||||||
|  |  | ||||||
|         vTaskDelay(TX_INTERVAL * 1000 / portTICK_PERIOD_MS); |         vTaskDelay(TX_INTERVAL * 1000 / portTICK_PERIOD_MS); | ||||||
|     } |     } | ||||||
| @ -49,7 +47,13 @@ void send_messages(void* pvParameter) | |||||||
|  |  | ||||||
| extern "C" void app_main(void) | extern "C" void app_main(void) | ||||||
| { | { | ||||||
|     gpio_install_isr_service(ESP_INTR_FLAG_IRAM); |     esp_err_t err; | ||||||
|  |     // Initialize the GPIO ISR handler service | ||||||
|  |     err = gpio_install_isr_service(ESP_INTR_FLAG_IRAM); | ||||||
|  |     ESP_ERROR_CHECK(err); | ||||||
|  |     // Initialize the NVS (non-volatile storage) for saving and restoring the keys | ||||||
|  |     err = nvs_flash_init(); | ||||||
|  |     ESP_ERROR_CHECK(err); | ||||||
|  |  | ||||||
|     // Initialize SPI bus |     // Initialize SPI bus | ||||||
|     spi_bus_config_t spi_bus_config; |     spi_bus_config_t spi_bus_config; | ||||||
| @ -61,15 +65,21 @@ extern "C" void app_main(void) | |||||||
|     spi_bus_config.max_transfer_sz = 0; |     spi_bus_config.max_transfer_sz = 0; | ||||||
|  |  | ||||||
|     esp_err_t ret = spi_bus_initialize(HSPI_HOST, &spi_bus_config, 1); |     esp_err_t ret = spi_bus_initialize(HSPI_HOST, &spi_bus_config, 1); | ||||||
|     assert(ret == ESP_OK); |     ESP_ERROR_CHECK(err); | ||||||
|  |  | ||||||
|     ttn.configurePins(HSPI_HOST, 18, TTN_NOT_CONNECTED, 14, 26, 33); |     ttn.configurePins(HSPI_HOST, 18, TTN_NOT_CONNECTED, 14, 26, 33); | ||||||
|  |  | ||||||
|  |     // The below line can be commented after the first run as the data is saved in NVS | ||||||
|     ttn.provision(devEui, appEui, appKey); |     ttn.provision(devEui, appEui, appKey); | ||||||
|  |  | ||||||
|     printf("Joining...\n"); |     printf("Joining...\n"); | ||||||
|     ttn.join(); |     if (ttn.join()) | ||||||
|     printf("Joined.\n"); |     { | ||||||
|  |         printf("Joined.\n"); | ||||||
|     xTaskCreate(send_messages, "send_messages", 1024 * 4, (void* )0, 3, NULL); |         xTaskCreate(sendMessages, "send_messages", 1024 * 4, (void* )0, 3, NULL); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         printf("Join failed. Goodbye\n"); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,3 +1,3 @@ | |||||||
| PROJECT_NAME := hello_world | PROJECT_NAME := send_recv | ||||||
|  |  | ||||||
| include $(IDF_PATH)/make/project.mk | include $(IDF_PATH)/make/project.mk | ||||||
|  | |||||||
| @ -6,11 +6,12 @@ | |||||||
|  * which accompanies this distribution, and is available at |  * which accompanies this distribution, and is available at | ||||||
|  * http://www.eclipse.org/legal/epl-v10.html |  * http://www.eclipse.org/legal/epl-v10.html | ||||||
|  * |  * | ||||||
|  * Sample program showing how to send a test message every 30 second. |  * Sample program showing how to send and receive messages. | ||||||
|  *******************************************************************************/ |  *******************************************************************************/ | ||||||
|  |  | ||||||
| #include "freertos/FreeRTOS.h" | #include "freertos/FreeRTOS.h" | ||||||
| #include "esp_event.h" | #include "esp_event.h" | ||||||
|  | #include "nvs_flash.h" | ||||||
|  |  | ||||||
| #include "TheThingsNetwork.h" | #include "TheThingsNetwork.h" | ||||||
|  |  | ||||||
| @ -38,10 +39,7 @@ void sendMessages(void* pvParameter) | |||||||
|     while (1) { |     while (1) { | ||||||
|         printf("Sending message...\n"); |         printf("Sending message...\n"); | ||||||
|         TTNResponseCode res = ttn.transmitBytes(msgData, sizeof(msgData) - 1); |         TTNResponseCode res = ttn.transmitBytes(msgData, sizeof(msgData) - 1); | ||||||
|         if (res == kTTNSuccessfulTransmission) |         printf(res == kTTNSuccessfulTransmission ? "Message sent.\n" : "Transmission failed.\n"); | ||||||
|             printf("Message sent.\n"); |  | ||||||
|         else |  | ||||||
|             printf("Transmission failed.\n"); |  | ||||||
|  |  | ||||||
|         vTaskDelay(TX_INTERVAL * 1000 / portTICK_PERIOD_MS); |         vTaskDelay(TX_INTERVAL * 1000 / portTICK_PERIOD_MS); | ||||||
|     } |     } | ||||||
| @ -57,7 +55,13 @@ void messageReceived(const uint8_t* message, size_t length, port_t port) | |||||||
|  |  | ||||||
| extern "C" void app_main(void) | extern "C" void app_main(void) | ||||||
| { | { | ||||||
|     gpio_install_isr_service(ESP_INTR_FLAG_IRAM); |     esp_err_t err; | ||||||
|  |     // Initialize the GPIO ISR handler service | ||||||
|  |     err = gpio_install_isr_service(ESP_INTR_FLAG_IRAM); | ||||||
|  |     ESP_ERROR_CHECK(err); | ||||||
|  |     // Initialize the NVS (non-volatile storage) for saving and restoring the keys | ||||||
|  |     err = nvs_flash_init(); | ||||||
|  |     ESP_ERROR_CHECK(err); | ||||||
|  |  | ||||||
|     // Initialize SPI bus |     // Initialize SPI bus | ||||||
|     spi_bus_config_t spi_bus_config; |     spi_bus_config_t spi_bus_config; | ||||||
| @ -68,18 +72,24 @@ extern "C" void app_main(void) | |||||||
|     spi_bus_config.quadhd_io_num = -1; |     spi_bus_config.quadhd_io_num = -1; | ||||||
|     spi_bus_config.max_transfer_sz = 0; |     spi_bus_config.max_transfer_sz = 0; | ||||||
|  |  | ||||||
|     esp_err_t ret = spi_bus_initialize(HSPI_HOST, &spi_bus_config, 1); |     err = spi_bus_initialize(HSPI_HOST, &spi_bus_config, 1); | ||||||
|     assert(ret == ESP_OK); |     ESP_ERROR_CHECK(err); | ||||||
|  |  | ||||||
|     ttn.configurePins(HSPI_HOST, 18, TTN_NOT_CONNECTED, 14, 26, 33); |     ttn.configurePins(HSPI_HOST, 18, TTN_NOT_CONNECTED, 14, 26, 33); | ||||||
|  |  | ||||||
|  |     // The below line can be commented after the first run as the data is saved in NVS | ||||||
|     ttn.provision(devEui, appEui, appKey); |     ttn.provision(devEui, appEui, appKey); | ||||||
|  |  | ||||||
|     ttn.onMessage(messageReceived); |     ttn.onMessage(messageReceived); | ||||||
|  |  | ||||||
|     printf("Joining...\n"); |     printf("Joining...\n"); | ||||||
|     ttn.join(); |     if (ttn.join()) | ||||||
|     printf("Joined.\n"); |     { | ||||||
|  |         printf("Joined.\n"); | ||||||
|     xTaskCreate(sendMessages, "send_messages", 1024 * 4, (void* )0, 3, NULL); |         xTaskCreate(sendMessages, "send_messages", 1024 * 4, (void* )0, 3, NULL); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         printf("Join failed. Goodbye\n"); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -90,7 +90,10 @@ public: | |||||||
|     /** |     /** | ||||||
|      * @brief Sets the information needed to activate the device via OTAA, without actually activating. |      * @brief Sets the information needed to activate the device via OTAA, without actually activating. | ||||||
|      *  |      *  | ||||||
|      * The provided EUIs and key are saved in non-volatile memory. Call join() without arguments to activate. |      * The provided device EUI, app EUI and app key are saved in non-volatile memory. Before | ||||||
|  |      * this function is called, 'nvs_flash_init' must have been called once. | ||||||
|  |      *  | ||||||
|  |      * Call join() without arguments to activate. | ||||||
|      *  |      *  | ||||||
|      * @param devEui  Device EUI (16 character string with hexadecimal data) |      * @param devEui  Device EUI (16 character string with hexadecimal data) | ||||||
|      * @param appEui  Application EUI of the device (16 character string with hexadecimal data) |      * @param appEui  Application EUI of the device (16 character string with hexadecimal data) | ||||||
| @ -101,9 +104,9 @@ public: | |||||||
|     bool provision(const char *devEui, const char *appEui, const char *appKey); |     bool provision(const char *devEui, const char *appEui, const char *appKey); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * @brief Set the EUIs and keys and activate the device via OTAA. |      * @brief Set the device EUI, app EUI and app key and activate the device via OTAA. | ||||||
|      *  |      *  | ||||||
|      * The EUIs and key are NOT saved in non-volatile memory. |      * The device EUI, app EUI and app key are NOT saved in non-volatile memory. | ||||||
|      *  |      *  | ||||||
|      * The function blocks until the activation has completed or failed. |      * The function blocks until the activation has completed or failed. | ||||||
|      *  |      *  | ||||||
| @ -119,6 +122,7 @@ public: | |||||||
|      * @brief Activate the device via OTAA. |      * @brief Activate the device via OTAA. | ||||||
|      *  |      *  | ||||||
|      * The app EUI, app key and dev EUI must already have been provisioned by a call to 'provision()'. |      * The app EUI, app key and dev EUI must already have been provisioned by a call to 'provision()'. | ||||||
|  |      * Before this function is called, 'nvs_flash_init' must have been called once. | ||||||
|      *  |      *  | ||||||
|      * The function blocks until the activation has completed or failed. |      * The function blocks until the activation has completed or failed. | ||||||
|      *  |      *  | ||||||
| @ -160,11 +164,23 @@ public: | |||||||
|      */ |      */ | ||||||
|     void onMessage(TTNMessageCallback callback); |     void onMessage(TTNMessageCallback callback); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @brief Checks if device EUI, app EUI and app key have been stored in non-volatile storage | ||||||
|  |      * or have been provided as by a call to 'join(const char*, const char*, const char*)'. | ||||||
|  |      *  | ||||||
|  |      * @return true   if they are stored, complete and of the correct size | ||||||
|  |      * @return false  otherwise | ||||||
|  |      */ | ||||||
|  |     bool isProvisioned(); | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     TTNMessageCallback messageCallback; |     TTNMessageCallback messageCallback; | ||||||
|  |     bool haveKeys; | ||||||
|  |  | ||||||
|  |     bool joinCore(); | ||||||
|     bool decodeKeys(const char *devEui, const char *appEui, const char *appKey); |     bool decodeKeys(const char *devEui, const char *appEui, const char *appKey); | ||||||
|  |     bool saveKeys(); | ||||||
|  |     bool restoreKeys(bool silent); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ | |||||||
|  |  | ||||||
| #include "freertos/FreeRTOS.h" | #include "freertos/FreeRTOS.h" | ||||||
| #include "esp_event.h" | #include "esp_event.h" | ||||||
|  | #include "nvs_flash.h" | ||||||
| #include "TheThingsNetwork.h" | #include "TheThingsNetwork.h" | ||||||
| #include "esp_log.h" | #include "esp_log.h" | ||||||
| #include "oslmic.h" | #include "oslmic.h" | ||||||
| @ -26,6 +27,10 @@ enum ClientAction | |||||||
| }; | }; | ||||||
|  |  | ||||||
| static const char *TAG = "ttn"; | 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 TheThingsNetwork* ttnInstance; | ||||||
| static uint8_t devEui[8]; | static uint8_t devEui[8]; | ||||||
| @ -35,6 +40,8 @@ static QueueHandle_t resultQueue; | |||||||
| static ClientAction clientAction = eActionUnrelated; | 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 bool hexStringToBin(const char *hex, uint8_t *buf, int len); | ||||||
| static int hexTupleToByte(const char *hex); | static int hexTupleToByte(const char *hex); | ||||||
| static int hexDigitToVal(char ch); | static int hexDigitToVal(char ch); | ||||||
| @ -42,6 +49,7 @@ static void swapByteOrder(uint8_t* buf, int len); | |||||||
|  |  | ||||||
|  |  | ||||||
| TheThingsNetwork::TheThingsNetwork() | TheThingsNetwork::TheThingsNetwork() | ||||||
|  |     : messageCallback(NULL), haveKeys(false) | ||||||
| { | { | ||||||
|     ASSERT(ttnInstance == NULL); |     ASSERT(ttnInstance == NULL); | ||||||
|     ttnInstance = this; |     ttnInstance = this; | ||||||
| @ -67,7 +75,7 @@ void TheThingsNetwork::configurePins(spi_host_device_t spi_host, uint8_t nss, ui | |||||||
|     reset(); |     reset(); | ||||||
|  |  | ||||||
|     resultQueue = xQueueCreate(12, sizeof(int)); |     resultQueue = xQueueCreate(12, sizeof(int)); | ||||||
|     assert(resultQueue != NULL); |     ASSERT(resultQueue != NULL); | ||||||
|     hal_startBgTask(); |     hal_startBgTask(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -80,11 +88,16 @@ void TheThingsNetwork::reset() | |||||||
|  |  | ||||||
| bool TheThingsNetwork::provision(const char *devEui, const char *appEui, const char *appKey) | 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) | bool TheThingsNetwork::decodeKeys(const char *devEui, const char *appEui, const char *appKey) | ||||||
| { | { | ||||||
|  |     haveKeys = false; | ||||||
|  |  | ||||||
|     if (strlen(devEui) != 16 || !hexStringToBin(devEui, ::devEui, 8)) |     if (strlen(devEui) != 16 || !hexStringToBin(devEui, ::devEui, 8)) | ||||||
|     { |     { | ||||||
|         ESP_LOGW(TAG, "Invalid device EUI: %s", devEui); |         ESP_LOGW(TAG, "Invalid device EUI: %s", devEui); | ||||||
| @ -107,6 +120,7 @@ bool TheThingsNetwork::decodeKeys(const char *devEui, const char *appEui, const | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     haveKeys = true; | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -115,11 +129,28 @@ bool TheThingsNetwork::join(const char *devEui, const char *appEui, const char * | |||||||
|     if (!decodeKeys(devEui, appEui, appKey)) |     if (!decodeKeys(devEui, appEui, appKey)) | ||||||
|         return false; |         return false; | ||||||
|      |      | ||||||
|     return join(); |     return joinCore(); | ||||||
| } | } | ||||||
|  |  | ||||||
| bool TheThingsNetwork::join() | 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(); |     hal_enterCriticalSection(); | ||||||
|     clientAction = eActionJoining; |     clientAction = eActionJoining; | ||||||
|     LMIC_startJoining(); |     LMIC_startJoining(); | ||||||
| @ -173,6 +204,120 @@ void TheThingsNetwork::onMessage(TTNMessageCallback callback) | |||||||
|     messageCallback = 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 --- | // --- LMIC functions --- | ||||||
|  |  | ||||||
|  | |||||||
| @ -84,7 +84,7 @@ static void hal_io_init() | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     dio_queue = xQueueCreate(12, sizeof(queue_item_t)); |     dio_queue = xQueueCreate(12, sizeof(queue_item_t)); | ||||||
|     assert(dio_queue != NULL); |     ASSERT(dio_queue != NULL); | ||||||
|  |  | ||||||
|     gpio_pad_select_gpio(lmic_pins.dio0); |     gpio_pad_select_gpio(lmic_pins.dio0); | ||||||
|     gpio_set_direction(lmic_pins.dio0, GPIO_MODE_INPUT); |     gpio_set_direction(lmic_pins.dio0, GPIO_MODE_INPUT); | ||||||
| @ -151,8 +151,8 @@ static void collect_spi_result() | |||||||
|  |  | ||||||
|     spi_transaction_t* trx; |     spi_transaction_t* trx; | ||||||
|     esp_err_t err = spi_device_get_trans_result(spi_handle, &trx, 100 / portTICK_PERIOD_MS); |     esp_err_t err = spi_device_get_trans_result(spi_handle, &trx, 100 / portTICK_PERIOD_MS); | ||||||
|     assert(err == ESP_OK); |     ESP_ERROR_CHECK(err); | ||||||
|     assert(trx == spi_trx_queue + tail); |     ASSERT(trx == spi_trx_queue + tail); | ||||||
|     spi_num_outstanding_trx--; |     spi_num_outstanding_trx--; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -163,7 +163,7 @@ static void submit_spi_trx() | |||||||
|  |  | ||||||
|     int head = spi_trx_queue_head; |     int head = spi_trx_queue_head; | ||||||
|     esp_err_t err = spi_device_queue_trans(spi_handle, spi_trx_queue + head, 100 / portTICK_PERIOD_MS); |     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++; |     spi_num_outstanding_trx++; | ||||||
|  |  | ||||||
|     head++; |     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); |     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"); |     ESP_LOGI(TAG, "SPI initialized"); | ||||||
| } | } | ||||||
| @ -459,5 +459,5 @@ void hal_startBgTask() { | |||||||
| void hal_failed(const char *file, u2_t line) | void hal_failed(const char *file, u2_t line) | ||||||
| { | { | ||||||
|     ESP_LOGE(TAG, "%s:%d", file, line); |     ESP_LOGE(TAG, "%s:%d", file, line); | ||||||
|     assert(0); |     ASSERT(0); | ||||||
| } | } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user