diff --git a/components/CommandManager/CommandManager/CommandManager.cpp b/components/CommandManager/CommandManager/CommandManager.cpp index 151b08e..7255b1d 100644 --- a/components/CommandManager/CommandManager/CommandManager.cpp +++ b/components/CommandManager/CommandManager/CommandManager.cpp @@ -25,6 +25,7 @@ std::unordered_map commandTypeMap = { {"get_device_mode", CommandType::GET_DEVICE_MODE}, {"set_led_duty_cycle", CommandType::SET_LED_DUTY_CYCLE}, {"get_led_duty_cycle", CommandType::GET_LED_DUTY_CYCLE}, + {"get_serial", CommandType::GET_SERIAL}, }; std::function CommandManager::createCommand(const CommandType type, std::string_view json) const @@ -97,6 +98,9 @@ std::function CommandManager::createCommand(const CommandType t case CommandType::GET_LED_DUTY_CYCLE: return [this] { return getLEDDutyCycleCommand(this->registry); }; + case CommandType::GET_SERIAL: + return [this] + { return getSerialNumberCommand(this->registry); }; default: return nullptr; } diff --git a/components/CommandManager/CommandManager/CommandManager.hpp b/components/CommandManager/CommandManager/CommandManager.hpp index ab9aa5b..53eeb7c 100644 --- a/components/CommandManager/CommandManager/CommandManager.hpp +++ b/components/CommandManager/CommandManager/CommandManager.hpp @@ -46,6 +46,7 @@ enum class CommandType GET_DEVICE_MODE, SET_LED_DUTY_CYCLE, GET_LED_DUTY_CYCLE, + GET_SERIAL, }; class CommandManager diff --git a/components/CommandManager/CommandManager/commands/device_commands.cpp b/components/CommandManager/CommandManager/commands/device_commands.cpp index 8accbbd..7579b74 100644 --- a/components/CommandManager/CommandManager/commands/device_commands.cpp +++ b/components/CommandManager/CommandManager/commands/device_commands.cpp @@ -1,5 +1,7 @@ #include "device_commands.hpp" #include "LEDManager.hpp" +#include "esp_mac.h" +#include // Implementation inspired by SummerSigh work, initial PR opened in openiris repo, adapted to this rewrite CommandResult setDeviceModeCommand(std::shared_ptr registry, std::string_view jsonPayload) @@ -197,3 +199,23 @@ CommandResult getDeviceModeCommand(std::shared_ptr registry) auto result = std::format("{{ \"mode\": \"{}\", \"value\": {} }}", modeStr, static_cast(currentMode)); return CommandResult::getSuccessResult(result); } + +CommandResult getSerialNumberCommand(std::shared_ptr /*registry*/) +{ + // Read MAC for STA interface + uint8_t mac[6] = {0}; + esp_read_mac(mac, ESP_MAC_WIFI_STA); + + char serial_no_sep[13]; + // Serial without separators (12 hex chars) + std::snprintf(serial_no_sep, sizeof(serial_no_sep), "%02X%02X%02X%02X%02X%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + char mac_colon[18]; + // MAC with colons + std::snprintf(mac_colon, sizeof(mac_colon), "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + auto result = std::format("{{ \"serial\": \"{}\", \"mac\": \"{}\" }}", serial_no_sep, mac_colon); + return CommandResult::getSuccessResult(result); +} diff --git a/components/CommandManager/CommandManager/commands/device_commands.hpp b/components/CommandManager/CommandManager/commands/device_commands.hpp index 9e89db4..3d3f36f 100644 --- a/components/CommandManager/CommandManager/commands/device_commands.hpp +++ b/components/CommandManager/CommandManager/commands/device_commands.hpp @@ -22,4 +22,6 @@ CommandResult startStreamingCommand(); CommandResult switchModeCommand(std::shared_ptr registry, std::string_view jsonPayload); -CommandResult getDeviceModeCommand(std::shared_ptr registry); \ No newline at end of file +CommandResult getDeviceModeCommand(std::shared_ptr registry); + +CommandResult getSerialNumberCommand(std::shared_ptr registry); \ No newline at end of file diff --git a/tools/openiris_setup.py b/tools/openiris_setup.py index 8aa97f2..62b5c90 100644 --- a/tools/openiris_setup.py +++ b/tools/openiris_setup.py @@ -439,6 +439,26 @@ class OpenIrisDevice: print(f"❌ Failed to parse LED duty cycle: {e}") return None + def get_serial_info(self) -> Optional[Tuple[str, str]]: + """Get device serial number and MAC address""" + response = self.send_command("get_serial") + if "error" in response: + print(f"❌ Failed to get serial/MAC: {response['error']}") + return None + try: + results = response.get("results", []) + if results: + result_data = json.loads(results[0]) + payload = result_data["result"] + if isinstance(payload, str): + payload = json.loads(payload) + serial = payload.get("serial") + mac = payload.get("mac") + return serial, mac + except Exception as e: + print(f"❌ Failed to parse serial/MAC: {e}") + return None + def monitor_logs(self): """Monitor device logs until interrupted""" print("📋 Monitoring device logs (Press Ctrl+C to exit)...") @@ -793,6 +813,14 @@ def get_led_duty_cycle(device: OpenIrisDevice, args=None): print(f"💡 Current LED duty cycle: {duty}%") +def get_serial(device: OpenIrisDevice, args=None): + info = device.get_serial_info() + if info is not None: + serial, mac = info +# print(f"🔑 Serial: {serial}") + print(f"🔗 MAC: {mac}") + + COMMANDS_MAP = { "1": scan_networks, "2": display_networks, @@ -806,6 +834,7 @@ COMMANDS_MAP = { "10": set_led_duty_cycle, "11": get_led_duty_cycle, "12": monitor_logs, + "13": get_serial, } @@ -904,10 +933,11 @@ def main(): print("8. 🚀 Start streaming mode") print("9. 🔄 Switch device mode (WiFi/UVC/Auto)") print("10. 💡 Update PWM Duty Cycle") - print("11. 💡Get PWM Duty Cycle") + print("11. 💡 Get PWM Duty Cycle") print("12. 📖 Monitor logs") + print("13. 🔑 Show Serial/MAC") print("exit. 🚪 Exit") - choice = input("\nSelect option (1-12): ").strip() + choice = input("\nSelect option (1-13): ").strip() if choice == "exit": break