Skip to content

Instantly share code, notes, and snippets.

@wduraes
Last active September 18, 2022 21:53
Show Gist options
  • Save wduraes/83c0c65740f58a22b26aeca327c1dc23 to your computer and use it in GitHub Desktop.
Save wduraes/83c0c65740f58a22b26aeca327c1dc23 to your computer and use it in GitHub Desktop.
Pre-requirement: before changing the ESP32 sample to use NVS, please follow the sample in the official repo to ensure the basic environment, toolchain and your code are all correct.
This file shows the changes needed to separate the device credentials from the sample binaries in 2 steps:
1. Add the Azure credentials to the device's NVS (non-volatile storage)
2. Change the sample so it can read NVS data
STEP 1
To store data into the ESP32 NVS, use the code from this gist: https://gist.github.com/wduraes/584d5d517ea59aaf2f4cc6835cd491d6
The best way to do it is to duplicate the sample called nvs_rw_value (under you ESP-IDF directory /examples/storage) and replace its nvs_value_example.c code for the gist above.
Add your own credentials (lines 12 to 16) and flash the device.
At this point, your device will have the credentials stored to the NVS.
Repeat this step for each device you wish to connect.
STEP 2
Open file demos\projects\ESPRESSIF\adu\main\azure_iot_freertos_esp32_main.c
Add the function below to read data from NVS
void readNVS()
{
// Initialize NVS
esp_err_t err = nvs_flash_init(); //TODO remove dup
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
// NVS partition was truncated and needs to be erased
// Retry nvs_flash_init
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
ESP_ERROR_CHECK( err );
LogInfo(("Opening Non-Volatile Storage (NVS) handle... "));
nvs_handle_t my_handle;
err = nvs_open("storage", NVS_READWRITE, &my_handle); //NVS area name - storage, opened as read and write, given to a handle
if (err != ESP_OK) {
LogInfo(("Error (%s) opening NVS handle!\n", esp_err_to_name(err)));
} else {
err = nvs_get_str(my_handle, "WIFI_SSID", value_WIFI_SSID, &value_WIFI_SSID_length);
switch (err) {
case ESP_OK:
LogInfo(("Read Wifi Credentials SUCCESS=[%s]",value_WIFI_SSID));
break;
case ESP_ERR_NVS_NOT_FOUND:
ESP_LOGI( TAG, "The Wi-Fi SSID value is not initialized yet!\n" );
break;
default :
ESP_LOGI( TAG, "Error reading Wifi Credentials\n" );
}
err = nvs_get_str(my_handle, "WIFI_PASSWORD", value_WIFI_PASSWORD, &value_WIFI_PASSWORD_length);
switch (err) {
case ESP_OK:
LogInfo(("Read Wifi Password SUCCESS=[%s]",value_WIFI_PASSWORD));
break;
case ESP_ERR_NVS_NOT_FOUND:
ESP_LOGI( TAG, "The SSID Password value is not initialized yet!\n" );
break;
default :
ESP_LOGI( TAG, "Error reading SSID Password Credentials\n" );
}
err = nvs_get_str(my_handle, "HUB_FQDN", value_HUB_FQDN, &value_HUB_FQDN_length);
switch (err) {
case ESP_OK:
LogInfo(("Read HUB FQDN value SUCCESS=[%s]",value_HUB_FQDN));
break;
case ESP_ERR_NVS_NOT_FOUND:
ESP_LOGI( TAG, "The HUB FQDN value is not initialized yet!\n" );
break;
default :
ESP_LOGI( TAG, "Error reading HUB FQDN value\n" );
}
err = nvs_get_str(my_handle, "DEVICE_ID", value_DEVICE_ID, &value_DEVICE_ID_length);
switch (err) {
case ESP_OK:
LogInfo(("Read Device ID SUCCESS=[%s]",value_DEVICE_ID));
break;
case ESP_ERR_NVS_NOT_FOUND:
ESP_LOGI( TAG, "The Device ID is not initialized yet!\n" );
break;
default :
ESP_LOGI( TAG, "Error reading Device ID\n" );
}
err = nvs_get_str(my_handle, "DEVICE_SYM_KEY", value_DEVICE_SYM_KEY, &value_DEVICE_SYM_KEY_length);
switch (err) {
case ESP_OK:
LogInfo(("Read Device Key SUCCESS=[%s]\r\n",value_DEVICE_SYM_KEY));
break;
case ESP_ERR_NVS_NOT_FOUND:
ESP_LOGI( TAG, "The Device Key value is not initialized yet!\n" );
break;
default :
ESP_LOGI( TAG, "Error reading Device Key\n" );
}
}
}
Add a call for that function under app_main, right before the call to connect network:
readNVS(); //function to read credentials from NVS
Add the NVS and ESP headers to deal with NVS:
#include "esp_system.h"
#include "nvs.h"
Also add the variables to be populated by NVS read (note I'm creating char arrays that are 32 characters long. If your device credentials are longer, adjust accordingly)
//to be populated with NVS reading values
static char value_WIFI_SSID[32];
static char value_WIFI_PASSWORD[32];
static size_t value_WIFI_SSID_length=32;
static size_t value_WIFI_PASSWORD_length=32;
Finally, change where the code get its wifi and password from:
comment out:
//.ssid = CONFIG_SAMPLE_IOT_WIFI_SSID,
//.password = CONFIG_SAMPLE_IOT_WIFI_PASSWORD,
then add the below:
//copies credentials values from NVS
memcpy( xWifiConfig.sta.ssid, value_WIFI_SSID, value_WIFI_SSID_length);
memcpy( xWifiConfig.sta.password, value_WIFI_PASSWORD, value_WIFI_PASSWORD_length);
Function to read NVS and populate Wifi and password data are fine now, however we still need to populate for hub FQDN, device id and key in a different file.
Open the file demos\sample_azure_iot_adu\sample_azure_iot_pnp_data_if.h
Add the extern variables below to allow for its use across the sample:
extern char value_HUB_FQDN[32];
extern char value_DEVICE_ID[32];
extern char value_DEVICE_SYM_KEY[64];
extern size_t value_HUB_FQDN_length;
extern size_t value_DEVICE_ID_length;
extern size_t value_DEVICE_SYM_KEY_length;
Finally, open the file demos\sample_azure_iot_adu\sample_azure_iot_adu.c
Add local variables for use:
char value_HUB_FQDN[32];
char value_DEVICE_ID[32];
char value_DEVICE_SYM_KEY[64];
size_t value_HUB_FQDN_length=32;
size_t value_DEVICE_ID_length=32;
size_t value_DEVICE_SYM_KEY_length=64;
Under the function prvAzureDemoTask replace the reading from current variables:
uint8_t * pucIotHubHostname = ( uint8_t * ) value_HUB_FQDN; //democonfigHOSTNAME;
uint8_t * pucIotHubDeviceId = ( uint8_t * ) value_DEVICE_ID; //democonfigDEVICE_ID;
uint32_t pulIothubHostnameLength = value_HUB_FQDN_length -1; //sizeof( democonfigHOSTNAME ) - 1;
uint32_t pulIothubDeviceIdLength = value_DEVICE_ID_length -1; //sizeof( democonfigDEVICE_ID ) - 1;
Also under #ifdef democonfigDEVICE_SYMMETRIC_KEY replace these 3 lines:
( const uint8_t * ) value_DEVICE_SYM_KEY, //democonfigDEVICE_SYMMETRIC_KEY,
value_DEVICE_SYM_KEY_length - 1, //sizeof( democonfigDEVICE_SYMMETRIC_KEY ) - 1,
Crypto_HMAC );
Done!
Now, your sample will read from NVS, and correctly populate wifi credentials and Azure credentials.
Compile and build once again and it should be working.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment