mirror of
https://github.com/manuelbl/ttn-esp32.git
synced 2025-06-22 15:04:28 +02:00
Generate device EUI from MAC
This commit is contained in:
parent
5cd2c7bac4
commit
302509d096
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user