Как найти и изменить MAC-адрес на ESP32
Каждый ESP32 имеет уникальный MAC-адрес, который жёстко прошит в чип и играет важную роль в обеспечении эффективной связи между устройствами. Однако бывают случаи, когда вам может потребоваться назначить новый MAC-адрес вашему ESP32. Например, вы можете сделать это в целях сетевой безопасности, например, для реализации белого списка MAC-адресов, который разрешает подключение к сети Wi-Fi только выбранным устройствам.
В таких случаях следующее руководство будет бесценным. Оно содержит пошаговые инструкции о том, как найти текущий MAC-адрес вашего ESP32 и как установить новый.
Что такое MAC-адрес?
MAC-адрес (сокращение от «media access control» — управление доступом к среде передачи) — это последовательность цифр и букв, которая служит уникальным идентификатором сетевого устройства. MAC-адреса состоят из 12 шестнадцатеричных символов, сгруппированных в шесть пар, например AA:BB:CC:DD:EE:FF.
Каждое устройство, подключающееся к сети, оснащено сетевым контроллером (NIC), который включает электронную схему, необходимую для связи по определённому сетевому протоколу, такому как Wi-Fi, Bluetooth или Ethernet. Производитель назначает уникальный MAC-адрес каждому NIC (если их несколько) в процессе производства, и этот адрес навсегда сохраняется в аппаратном обеспечении устройства.
Нам нужны эти адреса, чтобы иметь возможность отправлять или получать данные по сети. В то время как IP-адреса идентифицируют сетевое подключение, MAC-адреса идентифицируют оборудование. Однако, в отличие от IP-адресов, которые часто меняются, MAC-адреса являются статичными, поскольку используются только в локальной сети.
Хотя MAC-адрес обычно прошит в аппаратное обеспечение устройства, многие системы, включая ESP32, позволяют переопределить его программно. Но имейте в виду, что пользовательский MAC-адрес является временным и будет сброшен к заводскому значению при перезагрузке чипа, если вы не запрограммируете ESP32 устанавливать его при каждой загрузке.
MAC-адрес на ESP32
ESP32 имеет несколько MAC-адресов, по одному для каждого сетевого интерфейса, который он поддерживает, включая следующие:
Wi-Fi Station (STA)
Wi-Fi Access Point (AP)
Bluetooth-интерфейс (Classic и BLE)
Ethernet
Только первый из них, известный как базовый MAC-адрес, сохраняется в eFuse или внешнем хранилище и используется для генерации MAC-адресов для других интерфейсов.
Wi-Fi Station (STA) использует базовый MAC-адрес. Напротив, MAC-адрес Wi-Fi Access Point (AP) получается путём увеличения последнего октета базового MAC-адреса на единицу. Аналогично, MAC-адрес Bluetooth получается путём добавления двойки к последнему октету базового адреса, а MAC-адрес Ethernet — путём добавления тройки к последнему октету базового адреса.
Интерфейс |
MAC-адрес |
Пример |
|---|---|---|
Wi-Fi Station |
base_mac |
80:7D:3A:CB:12:5C |
Wi-Fi SoftAP |
base_mac +1 к последнему октету |
80:7D:3A:CB:12:5D |
Bluetooth |
base_mac +2 к последнему октету |
80:7D:3A:CB:12:5E |
Ethernet |
base_mac +3 к последнему октету |
80:7D:3A:CB:12:5F |
Для получения дополнительной информации обратитесь к документации Espressif.
Определение MAC-адреса
Чтобы найти MAC-адрес на ESP32, вы можете использовать Espressif IoT Development Framework (ESP-IDF) или Arduino IDE. Приведённый здесь пример будет для Arduino IDE.
Сначала убедитесь, что у вас установлена поддержка плат ESP32 в Arduino IDE:
Микроконтроллер ESP32 быстро стал одной из самых популярных плат среди любителей, инженеров и людей, интересующихся Интернетом вещей (IoT)…
Вот простой скетч для вывода MAC-адреса устройства:
#include <WiFi.h>
void setup(){
Serial.begin(115200);
// Variable to store the MAC address
uint8_t baseMac[6];
// Get MAC address of the WiFi station interface
esp_read_mac(baseMac, ESP_MAC_WIFI_STA);
Serial.print("Station MAC: ");
for (int i = 0; i < 5; i++) {
Serial.printf("%02X:", baseMac[i]);
}
Serial.printf("%02X\n", baseMac[5]);
// Get the MAC address of the Wi-Fi AP interface
esp_read_mac(baseMac, ESP_MAC_WIFI_SOFTAP);
Serial.print("SoftAP MAC: ");
for (int i = 0; i < 5; i++) {
Serial.printf("%02X:", baseMac[i]);
}
Serial.printf("%02X\n", baseMac[5]);
// Get the MAC address of the Bluetooth interface
esp_read_mac(baseMac, ESP_MAC_BT);
Serial.print("Bluetooth MAC: ");
for (int i = 0; i < 5; i++) {
Serial.printf("%02X:", baseMac[i]);
}
Serial.printf("%02X\n", baseMac[5]);
// Get the MAC address of the Ethernet interface
esp_read_mac(baseMac, ESP_MAC_ETH);
Serial.print("Ethernet MAC: ");
for (int i = 0; i < 5; i++) {
Serial.printf("%02X:", baseMac[i]);
}
Serial.printf("%02X\n", baseMac[5]);
}
void loop(){
}
После загрузки кода откройте монитор порта и установите скорость передачи данных 115200. Затем нажмите кнопку EN на ESP32. Вы должны увидеть MAC-адреса для каждого сетевого интерфейса, выведенные в монитор порта.
Объяснение кода:
Код начинается с подключения библиотеки WiFi, которая предоставляет необходимые функции для обработки операций Wi-Fi на ESP32.
#include "WiFi.h"
Внутри функции setup() мы начинаем с инициализации последовательной связи на скорости 115200 бит/с.
Serial.begin(115200);
Объявляется переменная с именем baseMac для хранения MAC-адреса. Эта переменная представляет собой массив из шести элементов типа uint8_t, которые являются беззнаковыми 8-битными целыми числами — идеально подходят для хранения байтов MAC-адреса, которые находятся в диапазоне от 00 до FF (шестнадцатеричное представление).
uint8_t baseMac[6];
Затем вызывается встроенная функция ESP32 esp_read_mac() с аргументами baseMac и ESP_MAC_WIFI_STA для чтения MAC-адреса интерфейса Wi-Fi Station и сохранения его в массиве baseMac.
esp_read_mac(baseMac, ESP_MAC_WIFI_STA);
Затем монитор порта выводит «Station MAC: «, за которым следует MAC-адрес. Цикл for проходит через первые пять элементов массива baseMac, форматируя каждый байт в две шестнадцатеричные цифры, за которыми следует двоеточие. После цикла шестой элемент массива baseMac выводится без завершающего двоеточия, что обозначает конец MAC-адреса.
Serial.print("Station MAC: ");
for (int i = 0; i < 5; i++) {
Serial.printf("%02X:", baseMac[i]);
}
Serial.printf("%02X\n", baseMac[5]);
Процесс повторяется для MAC-адреса Wi-Fi AP, на этот раз с аргументом ESP_MAC_WIFI_SOFTAP для чтения MAC-адреса интерфейса Wi-Fi Access Point.
esp_read_mac(baseMac, ESP_MAC_WIFI_SOFTAP);
Serial.print("SoftAP MAC: ");
for (int i = 0; i < 5; i++) {
Serial.printf("%02X:", baseMac[i]);
}
Serial.printf("%02X\n", baseMac[5]);
Далее MAC-адрес Bluetooth-интерфейса получается вызовом esp_read_mac() с аргументом ESP_MAC_BT.
esp_read_mac(baseMac, ESP_MAC_BT);
Serial.print("Bluetooth MAC: ");
for (int i = 0; i < 5; i++) {
Serial.printf("%02X:", baseMac[i]);
}
Serial.printf("%02X\n", baseMac[5]);
Аналогичным образом MAC-адрес Ethernet-интерфейса считывается с помощью ESP_MAC_ETH.
esp_read_mac(baseMac, ESP_MAC_ETH);
Serial.print("Ethernet MAC: ");
for (int i = 0; i < 5; i++) {
Serial.printf("%02X:", baseMac[i]);
}
Serial.printf("%02X\n", baseMac[5]);
Функция loop() пуста, поскольку MAC-адреса выводятся только один раз при сбросе ESP32.
void loop(){
}
Изменение MAC-адреса
Следующий код изменяет базовый MAC-адрес ESP32, а затем отображает обновлённые MAC-адреса для каждого сетевого интерфейса.
Примечание
Важно отметить, что вам нужно изменить только базовый MAC-адрес на ESP32, поскольку все остальные MAC-адреса для различных сетевых интерфейсов (Wi-Fi AP, Bluetooth и Ethernet) обновляются автоматически, так как они получены из базового адреса с определёнными смещениями.
Перед загрузкой кода необходимо внести одно изменение. Вы должны обновить переменную newMAC, указав свой пользовательский MAC-адрес:
uint8_t newMAC[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
После внесения изменений загрузите код.
#include <WiFi.h>
#include <esp_wifi.h>
// Define your new MAC address
uint8_t newMAC[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
void setup(){
Serial.begin(115200);
// Disable WiFi
WiFi.mode(WIFI_OFF);
Serial.println("[OLD]---");
FindMACAddress();
// Set the new MAC address
if (esp_base_mac_addr_set(newMAC) == ESP_OK) {
Serial.println("MAC address set successfully");
} else {
Serial.println("Failed to set MAC address");
}
Serial.println();
Serial.println("[NEW]---");
FindMACAddress();
}
void loop(){
}
void FindMACAddress(){
// Get the MAC address of the Wi-Fi station interface
uint8_t baseMac[6];
// Get MAC address for WiFi station
esp_read_mac(baseMac, ESP_MAC_WIFI_STA);
Serial.print("Station MAC: ");
for (int i = 0; i < 5; i++) {
Serial.printf("%02X:", baseMac[i]);
}
Serial.printf("%02X\n", baseMac[5]);
// Get the MAC address of the Wi-Fi AP interface
esp_read_mac(baseMac, ESP_MAC_WIFI_SOFTAP);
Serial.print("SoftAP MAC: ");
for (int i = 0; i < 5; i++) {
Serial.printf("%02X:", baseMac[i]);
}
Serial.printf("%02X\n", baseMac[5]);
// Get the MAC address of the Bluetooth interface
esp_read_mac(baseMac, ESP_MAC_BT);
Serial.print("Bluetooth MAC: ");
for (int i = 0; i < 5; i++) {
Serial.printf("%02X:", baseMac[i]);
}
Serial.printf("%02X\n", baseMac[5]);
// Get the MAC address of the Ethernet interface
esp_read_mac(baseMac, ESP_MAC_ETH);
Serial.print("Ethernet MAC: ");
for (int i = 0; i < 5; i++) {
Serial.printf("%02X:", baseMac[i]);
}
Serial.printf("%02X\n", baseMac[5]);
Serial.println();
}
После загрузки кода откройте монитор порта и установите скорость передачи данных 115200. Затем нажмите кнопку EN на ESP32. Вы должны увидеть как старые, так и новые MAC-адреса для интерфейсов Wi-Fi station, Wi-Fi access point, Bluetooth и Ethernet.
Пожалуйста, имейте в виду, что, как было объяснено ранее, внесённые изменения не перезаписывают навсегда MAC-адрес, установленный производителем. Таким образом, каждый раз при сбросе платы или загрузке нового кода MAC-адрес вернётся к значению по умолчанию, если вы не запрограммируете ESP32 устанавливать его при каждой загрузке.
Объяснение кода:
Код начинается с подключения библиотек WiFi.h и esp_wifi.h, которые предоставляют функции, необходимые для операций Wi-Fi и специфических функций ESP32 Wi-Fi.
#include <WiFi.h>
#include <esp_wifi.h>
Затем определяется новый MAC-адрес в виде массива из шести шестнадцатеричных байтов.
uint8_t newMAC[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
В функции setup() инициализируется монитор порта и отключается Wi-Fi, чтобы убедиться, что новый MAC-адрес установлен до начала любой активности Wi-Fi.
WiFi.mode(WIFI_OFF);
Далее вызывается функция FindMACAddress() для вывода текущих MAC-адресов различных интерфейсов. Функция FindMACAddress() — это, по сути, предыдущий фрагмент кода, который извлекает и выводит MAC-адреса, обёрнутый в функцию для модульности и повторного использования.
FindMACAddress();
Затем вызывается функция esp_base_mac_addr_set() с новым MAC-адресом. В случае успеха выводится сообщение с подтверждением. Если операция не удалась, отображается сообщение об ошибке.
if (esp_base_mac_addr_set(newMAC) == ESP_OK) {
Serial.println("MAC address set successfully");
} else {
Serial.println("Failed to set MAC address");
}
После установки нового MAC-адреса функция FindMACAddress() вызывается снова для отображения новых MAC-адресов.
FindMACAddress();
Наконец, функция loop() оставлена пустой, поскольку код должен выполняться только один раз при запуске.
void loop(){
}