What is the best practice to build firmware for IoT nodes with node specific credentials

I’m developing IoT nodes (LoRaWAN). The nodes are all the same but for activation to the LoRaWAN network (TTN), each node has to include a set of ids, different to each node.
So I generate automaticaly let say 15 access_key.h files, access_key_001.h to access_key_015.h which include the ids. Now I have to build and load the firmware files for:

main.cpp + access_key_001.h
main.cpp + access_key_002.h

What is the best practice to do that with platformio? I already have moved the include-statement for access_key_001.h to platformio.ini with source_build_flags = -include “access_key_001.h”. So for the next node I change ‘by hand’ the _001.h to _002.h and so on. What is the suggestion to do this in a more automated way? Dynamic variables, how to? Scripting, how to?
Thanks for your ideas / suggestions.

You may get some ideas by reading Access upload verbose info.

The most time-efficient way to build those firmwares is to exactly not recompile the firmware for every new node. (Okay for 15 nodes this might be feasible, but beyond that quickly not). The linked topic describes ideas on how e.g. setup a global array where the keys are stored, or by using EEPROM / the end of flash they’re stored and read from constant addresses, then the firmware is compiled once, and through the address information in the ELF file one can just manipulate the once-created .bin file at the right spots to change the keys. This is especially usefull for your LoRaWAN systems where the stuff you have to overwrite is fixed-length, in the ABP case two 128-bit AES keys and a 4-byte device address, for OTAA equivalently some EUIDs etc… Such a “read address of key arrays from ELF (or know constant address beforehand), iterate through 15 sets of keys from a csv file or wherever, duplicate original firmware.bin and inject keys in the right places” script in e.g. Python is a million times faster than having to go through the build system over and over again. This scales.

Of course you can still go through the build system, but expect the appropriate recompilation and relinking times then. Advanced scripting or environment variables should be your starting point there. For the simplest case, you can have your platformio.ini do something like

build_flags = -I${sysenv.LORAWAN_KEYS_DIR}

and then write a small wrapper script in batch, shell or Python that sets the LORAWAN_KEYS_DIR variable to the directory where the appropriate access key is stored and executes pio run to kick of compilation – this assumes that you have a folder structure like

  | - node_01
       | - access_keys.h
  | - node_02
       | - access_keys.h

and the code doing a #include <access_keys.h> to load them in – then depending on which -I flag is given to add a certain directory to the path (e.g., -Ilorawan_keys/node_01), it will find the access_keys.h file in that specific folder.

There are of course many different ways to solve that.

Hello Max,
thanks, I highly appreciate your comments, hints, solutions and tips you give in this forum. This is really high quality. I follow the weekly community summary to see if there are topics I can learn from.

I will carefully read your helpful suggestions for my topic and try to develop the firmware in this direction.

Thanks again Wolfgang