mirror of
				https://github.com/manuelbl/ttn-esp32.git
				synced 2025-10-31 10:40:35 +01:00 
			
		
		
		
	Generate device EUI from MAC
This commit is contained in:
		
							
								
								
									
										4
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							| @ -4,6 +4,8 @@ | ||||
|         "config.h": "c", | ||||
|         "sdkconfig.h": "c", | ||||
|         "oslmic.h": "c", | ||||
|         "hal_esp32.h": "c" | ||||
|         "hal_esp32.h": "c", | ||||
|         "esp_log.h": "c", | ||||
|         "nvs_flash.h": "c" | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								examples/mac_address/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								examples/mac_address/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| PROJECT_NAME := mac_address | ||||
|  | ||||
| include $(IDF_PATH)/make/project.mk | ||||
							
								
								
									
										0
									
								
								examples/mac_address/main/component.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								examples/mac_address/main/component.mk
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										96
									
								
								examples/mac_address/main/main.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								examples/mac_address/main/main.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,96 @@ | ||||
| /******************************************************************************* | ||||
|  *  | ||||
|  * ttn-esp32 - The Things Network device library for ESP-IDF / SX127x | ||||
|  *  | ||||
|  * Copyright (c) 2018 Manuel Bleichenbacher | ||||
|  *  | ||||
|  * Licensed under MIT License | ||||
|  * https://opensource.org/licenses/MIT | ||||
|  * | ||||
|  * Sample program showing how to provision the keys from the built-in MAC. | ||||
|  *******************************************************************************/ | ||||
|  | ||||
| #include "freertos/FreeRTOS.h" | ||||
| #include "esp_event.h" | ||||
| #include "nvs_flash.h" | ||||
|  | ||||
| #include "TheThingsNetwork.h" | ||||
|  | ||||
| // NOTE: | ||||
| // The LoRaWAN frequency and the radio chip must be configured by running 'make menuconfig'. | ||||
| // Go to Components / The Things Network, select the appropriate values and save. | ||||
|  | ||||
| // Copy the below two lines from the bottom | ||||
| // of your device's overview page in the TTN console. | ||||
| const char *appEui = "????????????????"; | ||||
| const char *appKey = "????????????????????????????????"; | ||||
|  | ||||
| // Pins and other resources | ||||
| #define TTN_SPI_HOST      HSPI_HOST | ||||
| #define TTN_SPI_DMA_CHAN  1 | ||||
| #define TTN_PIN_SPI_SCLK  5 | ||||
| #define TTN_PIN_SPI_MOSI  27 | ||||
| #define TTN_PIN_SPI_MISO  19 | ||||
| #define TTN_PIN_NSS       18 | ||||
| #define TTN_PIN_RXTX      TTN_NOT_CONNECTED | ||||
| #define TTN_PIN_RST       TTN_NOT_CONNECTED | ||||
| #define TTN_PIN_DIO0      26 | ||||
| #define TTN_PIN_DIO1      33 | ||||
|  | ||||
| static TheThingsNetwork ttn; | ||||
|  | ||||
| const unsigned TX_INTERVAL = 30; | ||||
| static uint8_t msgData[] = "Hello, world"; | ||||
|  | ||||
|  | ||||
| void sendMessages(void* pvParameter) | ||||
| { | ||||
|     while (1) { | ||||
|         printf("Sending message...\n"); | ||||
|         TTNResponseCode res = ttn.transmitMessage(msgData, sizeof(msgData) - 1); | ||||
|         printf(res == kTTNSuccessfulTransmission ? "Message sent.\n" : "Transmission failed.\n"); | ||||
|  | ||||
|         vTaskDelay(TX_INTERVAL * 1000 / portTICK_PERIOD_MS); | ||||
|     } | ||||
| } | ||||
|  | ||||
| extern "C" void app_main(void) | ||||
| { | ||||
|     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 | ||||
|     spi_bus_config_t spi_bus_config; | ||||
|     spi_bus_config.miso_io_num = TTN_PIN_SPI_MISO; | ||||
|     spi_bus_config.mosi_io_num = TTN_PIN_SPI_MOSI; | ||||
|     spi_bus_config.sclk_io_num = TTN_PIN_SPI_SCLK; | ||||
|     spi_bus_config.quadwp_io_num = -1; | ||||
|     spi_bus_config.quadhd_io_num = -1; | ||||
|     spi_bus_config.max_transfer_sz = 0; | ||||
|     err = spi_bus_initialize(TTN_SPI_HOST, &spi_bus_config, TTN_SPI_DMA_CHAN); | ||||
|     ESP_ERROR_CHECK(err); | ||||
|  | ||||
|     // Configure the SX127x pins | ||||
|     ttn.configurePins(TTN_SPI_HOST, TTN_PIN_NSS, TTN_PIN_RXTX, TTN_PIN_RST, TTN_PIN_DIO0, TTN_PIN_DIO1); | ||||
|  | ||||
|     ttn.provisionWithMAC(appEui, appKey); | ||||
|  | ||||
|     ttn.startProvisioningTask(); | ||||
|  | ||||
|     printf("Joining...\n"); | ||||
|     if (ttn.join()) | ||||
|     { | ||||
|         printf("Joined.\n"); | ||||
|         xTaskCreate(sendMessages, "send_messages", 1024 * 4, (void* )0, 3, NULL); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         printf("Join failed. Goodbye\n"); | ||||
|     } | ||||
| } | ||||
| @ -104,6 +104,32 @@ public: | ||||
|      */ | ||||
|     bool provision(const char *devEui, const char *appEui, const char *appKey); | ||||
|  | ||||
|     /** | ||||
|      * @brief Sets the information needed to activate the device via OTAA, using the MAC to generate the device EUI | ||||
|      * and without actually activating. | ||||
|      *  | ||||
|      * The generated device EUI and the provided app EUI and app key are saved in non-volatile memory. Before | ||||
|      * this function is called, 'nvs_flash_init' must have been called once. | ||||
|      *  | ||||
|      * The device EUI is generated by retrieving the ESP32's WiFi MAC address and expanding it into a device EUI | ||||
|      * by adding FFFE in the middle. So the MAC address A0:B1:C2:01:02:03 becomes the EUI A0:B1:C2:FF:FE:01:02:03. | ||||
|      * The TTN console requires the device EUI in MSB format, so it has to be reversed and entered as | ||||
|      * "03 02 01 FE FF C2 B1 A0". | ||||
|      *  | ||||
|      * Generating the device EUI from the MAC address allows to flash the same app EUI and app key to a batch of | ||||
|      * devices. However, using the same app key for multiple devices is insecure. Only use this approach if | ||||
|      * it is okay for that the LoRa communication of your application can easily be intercepted and that | ||||
|      * forged data can be injected. | ||||
|      *  | ||||
|      * Call join() without arguments to activate. | ||||
|      *  | ||||
|      * @param appEui  Application EUI of the device (16 character string with hexadecimal data) | ||||
|      * @param appKey  App Key of the device (32 character string with hexadecimal data) | ||||
|      * @return true   if the provisioning was successful | ||||
|      * @return false  if the provisioning failed | ||||
|      */ | ||||
|     bool provisionWithMAC(const char *appEui, const char *appKey); | ||||
|  | ||||
|     /** | ||||
|      * @brief Start task that listens on configured UART for provisioning commands. | ||||
|      *  | ||||
|  | ||||
| @ -86,6 +86,14 @@ bool TheThingsNetwork::provision(const char *devEui, const char *appEui, const c | ||||
|     return provisioning_save_keys(); | ||||
| } | ||||
|  | ||||
| bool TheThingsNetwork::provisionWithMAC(const char *appEui, const char *appKey) | ||||
| { | ||||
|     if (!provisioning_from_mac(appEui, appKey)) | ||||
|         return false; | ||||
|      | ||||
|     return provisioning_save_keys(); | ||||
| } | ||||
|  | ||||
| void TheThingsNetwork::startProvisioningTask() | ||||
| { | ||||
| #if !defined(CONFIG_TTN_PROVISION_UART_NONE) | ||||
|  | ||||
| @ -14,6 +14,7 @@ | ||||
| #include "driver/uart.h" | ||||
| #include "esp_event.h" | ||||
| #include "esp_log.h" | ||||
| #include "esp_system.h" | ||||
| #include "nvs_flash.h" | ||||
| #include "provisioning.h" | ||||
| #include "lmic.h" | ||||
| @ -28,6 +29,7 @@ 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 bool provisioning_decode(bool incl_dev_eui, const char *dev_eui, const char *app_eui, const char *app_key); | ||||
| static void provisioning_task(void* pvParameter); | ||||
| static void provisioning_add_line_data(int numBytes); | ||||
| static void provisioning_detect_line_end(int start_at); | ||||
| @ -195,6 +197,7 @@ void provisioning_process_line() | ||||
|     // Expected format: | ||||
|     // AT+PROV? | ||||
|     // AT+PROV=hex16-hex16-hex32 | ||||
|     // AT+MAC? | ||||
|     if (strcmp(line_buf, "AT+PROV?") == 0) | ||||
|     { | ||||
|         uint8_t binbuf[8]; | ||||
| @ -233,6 +236,22 @@ void provisioning_process_line() | ||||
|             is_ok = false; | ||||
|         } | ||||
|     } | ||||
|     else if (strcmp(line_buf, "AT+MAC?") == 0) | ||||
|     { | ||||
|         uint8_t mac[6]; | ||||
|         char hexbuf[12]; | ||||
|  | ||||
|         esp_err_t err = esp_efuse_mac_get_default(mac); | ||||
|         ESP_ERROR_CHECK(err); | ||||
|  | ||||
|         bin_to_hex_str(mac, 6, hexbuf); | ||||
|         for (int i = 0; i < 12; i += 2) { | ||||
|             if (i > 0) | ||||
|                 uart_write_bytes(UART_NUM, ":", 1); | ||||
|             uart_write_bytes(UART_NUM, hexbuf + i, 2); | ||||
|         } | ||||
|         uart_write_bytes(UART_NUM, "\r\n", 2); | ||||
|     } | ||||
|     else if (strcmp(line_buf, "AT+PROVQ") == 0) | ||||
|     { | ||||
|         quit_task = true; | ||||
| @ -276,18 +295,42 @@ bool provisioning_have_keys() | ||||
| } | ||||
|  | ||||
| bool provisioning_decode_keys(const char *dev_eui, const char *app_eui, const char *app_key) | ||||
| { | ||||
|     return provisioning_decode(true, dev_eui, app_eui, app_key); | ||||
| } | ||||
|  | ||||
| bool provisioning_from_mac(const char *app_eui, const char *app_key) | ||||
| { | ||||
|     uint8_t mac[6]; | ||||
|     esp_err_t err = esp_efuse_mac_get_default(mac); | ||||
|     ESP_ERROR_CHECK(err); | ||||
|      | ||||
|     global_dev_eui[0] = mac[0]; | ||||
|     global_dev_eui[1] = mac[1]; | ||||
|     global_dev_eui[2] = mac[2]; | ||||
|     global_dev_eui[3] = 0xff; | ||||
|     global_dev_eui[4] = 0xfe; | ||||
|     global_dev_eui[5] = mac[3]; | ||||
|     global_dev_eui[6] = mac[4]; | ||||
|     global_dev_eui[7] = mac[5]; | ||||
|  | ||||
|     return provisioning_decode(false, NULL, app_eui, app_key); | ||||
| } | ||||
|  | ||||
| bool provisioning_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_app_eui[8]; | ||||
|     uint8_t buf_app_key[16]; | ||||
|  | ||||
|     if (strlen(dev_eui) != 16 || !hex_str_to_bin(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); | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     swap_bytes(buf_dev_eui, 8); | ||||
|     if (incl_dev_eui) | ||||
|         swap_bytes(buf_dev_eui, 8); | ||||
|  | ||||
|     if (strlen(app_eui) != 16 || !hex_str_to_bin(app_eui, buf_app_eui, 8)) | ||||
|     { | ||||
| @ -303,7 +346,8 @@ bool provisioning_decode_keys(const char *dev_eui, const char *app_eui, const ch | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     memcpy(global_dev_eui, buf_dev_eui, sizeof(global_dev_eui)); | ||||
|     if (incl_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_key, buf_app_key, sizeof(global_app_key)); | ||||
|  | ||||
|  | ||||
| @ -24,6 +24,7 @@ extern "C" { | ||||
| void provisioning_start_task(); | ||||
| bool provisioning_have_keys(); | ||||
| bool provisioning_decode_keys(const char *dev_eui, const char *app_eui, const char *app_key); | ||||
| bool provisioning_from_mac(const char *app_eui, const char *app_key); | ||||
| bool provisioning_save_keys(); | ||||
| bool provisioning_restore_keys(bool silent); | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user