diff --git a/README.md b/README.md index 51f11440..b68c44f8 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,7 @@ wifi.status | `wifi clear` | Clear runtime creds (fall back to compile-time on next boot) | | `tcp on` / `tcp off` / `tcp status` | Control/query the TCP server | | `ble on` / `ble off` / `ble status` | Control/query Bluetooth | +| `mac` | Show the device Wi-Fi and BLE MAC addresses (also `get mac`, `get wifi.mac`, `get ble.mac` in the app console or over USB serial) | | `ota check` | Ask the OTA server whether a newer build exists for this device | | `ota update` | Install that build over Wi-Fi (see [Update over Wi-Fi](#update-over-wi-fi)) | diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 9b943206..1f21772e 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -12,6 +12,9 @@ #ifdef ESP32 #include // esp_restart for the "bootloader" CLI command #include // RTC_CNTL_OPTION1_REG / FORCE_DOWNLOAD_BOOT +#if __has_include() +#include // esp_read_mac for the "mac" / "get mac" CLI commands +#endif #endif #include #include @@ -227,7 +230,27 @@ static const char* kMeshcomodHelpMsg = "tcp status\n" "ble on\n" "ble off\n" - "ble status"; + "ble status\n" + "mac"; + +// Factory MAC of one ESP32 interface as "AA:BB:CC:DD:EE:FF", or "n/a" when the chip has no +// such interface (ESP32-S2 has no Bluetooth) or this is not an ESP32. The address is read from +// eFuse, so it is valid whether or not that radio is currently on. +#ifdef ESP32 +static void formatDeviceMac(esp_mac_type_t type, char* out, size_t len) { + uint8_t m[6]; + if (esp_read_mac(m, type) == ESP_OK) { + snprintf(out, len, "%02X:%02X:%02X:%02X:%02X:%02X", m[0], m[1], m[2], m[3], m[4], m[5]); + } else { + StrHelper::strncpy(out, "n/a", len); + } +} +static void getWifiMac(char* out, size_t len) { formatDeviceMac(ESP_MAC_WIFI_STA, out, len); } +static void getBleMac(char* out, size_t len) { formatDeviceMac(ESP_MAC_BT, out, len); } +#else +static void getWifiMac(char* out, size_t len) { StrHelper::strncpy(out, "n/a", len); } +static void getBleMac(char* out, size_t len) { StrHelper::strncpy(out, "n/a", len); } +#endif #define MESHCOMOD_CMD_CACHE_SIZE 6 struct MeshcomodCmdCacheEntry { @@ -571,6 +594,14 @@ bool MyMesh::handleMeshcomodCommand(const char* text, int text_len) { pushMeshcomodReply(r); return true; } + if (isCmd(p, "mac")) { + char wifi[20], ble[20], r[64]; + getWifiMac(wifi, sizeof wifi); + getBleMac(ble, sizeof ble); + snprintf(r, sizeof r, "wifi mac: %s\nble mac: %s", wifi, ble); + pushMeshcomodReply(r); + return true; + } if (isCmd(p, "advert.zerohop")) { pushMeshcomodReply(sendAdvert(false) ? "advert sent (zero-hop)" : "advert failed"); return true; @@ -4086,6 +4117,26 @@ bool MyMesh::handleCommand(const char* command, uint32_t sender_timestamp, char* return true; } + if (strcmp(command, "get wifi.mac") == 0) { + char mac[20]; + getWifiMac(mac, sizeof(mac)); + sprintf(reply, "> %s", mac); + return true; + } + if (strcmp(command, "get ble.mac") == 0) { + char mac[20]; + getBleMac(mac, sizeof(mac)); + sprintf(reply, "> %s", mac); + return true; + } + if (strcmp(command, "get mac") == 0) { + char wifi[20], ble[20]; + getWifiMac(wifi, sizeof(wifi)); + getBleMac(ble, sizeof(ble)); + sprintf(reply, "> wifi=%s ble=%s", wifi, ble); + return true; + } + if (strcmp(command, "get tz.offset") == 0 || memcmp(command, "set tz.offset ", 14) == 0) { strcpy(reply, "Error: unsupported"); return true; diff --git a/examples/companion_radio/ui-touch/UITask.cpp b/examples/companion_radio/ui-touch/UITask.cpp index b423c54b..a450dad4 100644 --- a/examples/companion_radio/ui-touch/UITask.cpp +++ b/examples/companion_radio/ui-touch/UITask.cpp @@ -9124,6 +9124,7 @@ static const AdminCmdEntry k_term_cmds[] = { { "ver - firmware version", "ver" }, { "clock - show RTC time", "clock" }, { "status - device status", "status" }, + { "mac - wifi/ble MAC addresses", "mac" }, { "get - show radio params", "get" }, { "[ RADIO / MESH ]", nullptr }, { "advert - flood advert", "advert" }, @@ -9432,7 +9433,7 @@ static void termCmdExit() { static bool termIsCliKeyword(const char* word, size_t len) { static const char* kw[] = { "help", "ver", "version", "clock", "time", "status", "get", "set", - "advert", "advert.zerohop", "reboot", "wifi", "tcp", "ble", "ota", + "advert", "advert.zerohop", "reboot", "wifi", "tcp", "ble", "ota", "mac", "ok", "cancel", }; for (const char* k : kw) {