Каждый модуль ESP32 имеет уникальный MAC-адрес, который жестко закодирован в чипе и играет важную роль в обеспечении эффективной связи между устройствами. Однако бывают случаи, когда вам может потребоваться назначить новый MAC-адрес вашему ESP32. Например, вы можете захотеть сделать это в целях сетевой безопасности, например, для реализации белого списка MAC-адресов, который позволяет только выбранным устройствам подключаться к сети Wi-Fi.
В таких случаях наш урок будет бесценным. Он содержит пошаговые инструкции о том, как узнать текущий MAC-адрес вашего ESP32 и как установить новый.
Что такое MAC-адрес?
MAC-адрес (сокращение от «media access control») — это ряд цифр и букв, который служит уникальным идентификатором сетевого устройства. MAC-адреса состоят из 12 шестнадцатеричных символов, сгруппированных в шесть пар, например AA:BB:CC:DD:EE:FF.
Каждое устройство, подключаемое к сети, оснащено контроллером сетевого интерфейса (network interface controller, NIC), который включает в себя электронные схемы, необходимые для связи через определенный сетевой протокол, такой как Wi-Fi, Bluetooth или Ethernet. Производитель назначает уникальный MAC-адрес каждому NIC (если их несколько) в процессе производства, и этот адрес постоянно хранится в аппаратном обеспечении устройства.
Эти адреса нужны нам для отправки и получения данных по сети. В то время как IP-адреса идентифицируют сетевое соединение, MAC-адреса идентифицируют оборудование. Однако, в отличие от IP-адресов, которые часто меняются, MAC-адреса статичны, поскольку они используются только в локальной сети.
Хотя MAC-адрес обычно зашит в аппаратную часть устройства, но многие системы, включая и модуль ESP32, позволяют переопределять его с помощью программного обеспечения. Но имейте в виду, что пользовательский MAC-адрес является временным и будет сброшен до значения по умолчанию производителя при сбросе чипа, если только вы не запрограммируете ESP32 на установку его при каждой загрузке.
MAC-адрес на ESP32
ESP32 имеет несколько MAC-адресов, по одному для каждого поддерживаемого сетевого интерфейса, включая следующие:
-
- Станция Wi-Fi (STA);
- Точка доступа Wi-Fi (AP);
- Интерфейс Bluetooth (классический и BLE);
- Ethernet.
Только первый из них, известный как базовый MAC-адрес, сохраняется в eFuse или внешнем хранилище и используется для генерации MAC-адресов для других интерфейсов.
Wi-Fi Station (STA) использует базовый MAC-адрес. Напротив, MAC-адрес Wi-Fi Access Point (AP) выводится путем увеличения последнего октета базового MAC-адреса на единицу. Аналогично, Bluetooth MAC-адрес выводится путем добавления двух к последнему октету базового адреса, а Ethernet MAC-адрес — путем добавления трех к последнему октету базового адреса. Более наглядно это представлено в следующей таблице.
Интерфейс | MAC-адрес | Пример |
Wi-Fi-станция | 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-адреса ESP32
Чтобы найти MAC-адрес на ESP32, вы можете использовать Espressif IoT Development Framework (ESP-IDF) или Arduino IDE. Приведенный здесь пример будет для Arduino IDE.
Сначала убедитесь, что в вашей среде Arduino IDE установлена поддержка платы ESP32.
Вот простой пример для распечатки MAC-адреса устройства:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#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.
1 |
#include "WiFi.h" |
Внутри функции setup() мы начинаем с инициирования последовательной связи со скоростью передачи данных 115200 бит/с.
1 |
Serial.begin(115200); |
Переменная с именем baseMac объявлена для хранения MAC-адреса. Эта переменная представляет собой массив из шести uint8_t
элементов, которые являются беззнаковыми 8-битными целыми числами, идеально подходящими для хранения байтов MAC-адреса в диапазоне от 00 до FF (Hex).
1 |
uint8_t baseMac[6]; |
Затем вызывается встроенная функция ESP32 esp_read_mac() с аргументами baseMac
и ESP_MAC_WIFI_STA
для считывания MAC-адреса интерфейса Wi-Fi Station и сохранения его в baseMac
массиве.
1 |
esp_read_mac(baseMac, ESP_MAC_WIFI_STA); |
Затем в окне монитора последовательной связи печатается «Station MAC:», а затем MAC-адрес. Цикл for
проходит по первым пяти элементам массива baseMac
, форматируя каждый байт в две шестнадцатеричные цифры, за которыми следует двоеточие. После цикла шестой элемент массива baseMac
печатается без конечного двоеточия, отмечая конец MAC-адреса.
1 2 3 4 5 |
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, на этот раз с ESP_MAC_WIFI_SOFTAP
аргументом для чтения MAC-адреса для интерфейса точки доступа Wi-Fi.
1 2 3 4 5 6 |
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
.
1 2 3 4 5 6 |
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
.
1 2 3 4 5 6 |
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.
1 2 |
void loop(){ } |
Изменение MAC-адреса ESP32
Следующий код изменяет базовый MAC-адрес ESP32, а затем отображает обновленные MAC-адреса для каждого сетевого интерфейса.
Примечание: важно отметить, что вам нужно изменить только базовый MAC-адрес на ESP32, поскольку все остальные MAC-адреса для различных сетевых интерфейсов (точка доступа Wi-Fi, Bluetooth и Ethernet) автоматически обновляются, поскольку они выводятся из базового адреса с определенными смещениями.
Перед загрузкой кода необходимо сделать одно изменение. Вы должны обновить переменную newMAC
- в нее вы должны записать ваш пользовательский MAC-адрес (то есть новый адрес, который вы хотите назначить вашему ESP32):
1 |
uint8_t newMAC[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; |
После внесения изменений загрузите код.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
#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, точки доступа Wi-Fi, интерфейсов Bluetooth и Ethernet.
Пожалуйста, имейте в виду, что, как объяснялось ранее, внесенные изменения не перезаписывают навсегда MAC-адрес, установленный производителем. Таким образом, каждый раз, когда вы сбрасываете плату или загружаете новый код, она будет возвращаться к своему MAC-адресу по умолчанию, если только вы не запрограммируете ESP32 на установку его при каждой загрузке.
Пояснение кода
Код начинается с подключения библиотек WiFi.h
и esp_wifi.h
, которые предоставляют функции, необходимые для работы Wi-Fi и определенных функций ESP32 Wi-Fi.
1 2 |
#include <WiFi.h> #include <esp_wifi.h> |
Затем новый MAC-адрес определяется как массив из шести шестнадцатеричных байтов.
1 |
uint8_t newMAC[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; |
В функции setup() инициализируется последовательный монитор и отключается Wi-Fi, чтобы гарантировать установку нового MAC-адреса до начала любой активности Wi-Fi.
1 |
WiFi.mode(WIFI_OFF); |
Далее вызывается функция FindMACAddress()
для печати текущих MAC-адресов для различных интерфейсов. Функция FindMACAddress()
в основном представляет собой предыдущий сегмент кода, который извлекает и печатает MAC-адреса, обернутый в функцию для модульности и возможности повторного использования.
1 |
FindMACAddress(); |
Затем функция esp_base_mac_addr_set()
вызывается с новым MAC-адресом. В случае успеха выводится сообщение с подтверждением. В случае неудачи выводится сообщение об ошибке.
1 2 3 4 5 |
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-адресов.
1 |
FindMACAddress(); |
Наконец, функция loop() остается пустой, поскольку код должен быть выполнен только один раз при запуске.
1 2 |
void loop(){ } |