smart-home/device_id_fetcher.py
2026-02-26 09:16:34 +08:00

210 lines
7.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ESP32设备ID获取工具
通过HTTP API远程获取ESP32硬件标识符无需烧录固件
"""
import requests
import json
import time
from datetime import datetime
class ESP32DeviceManager:
def __init__(self, device_ip="192.168.1.3", port=80):
self.device_ip = device_ip
self.port = port
self.base_url = f"http://{device_ip}:{port}/api/device"
def log_message(self, message):
"""打印带时间戳的日志"""
timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
print(f"[{timestamp}] {message}")
def get_device_id(self):
"""获取设备ID简化版"""
try:
response = requests.get(f"{self.base_url}/id", timeout=5)
if response.status_code == 200:
data = response.json()
return data
else:
self.log_message(f"❌ 获取设备ID失败: HTTP {response.status_code}")
return None
except requests.exceptions.RequestException as e:
self.log_message(f"❌ 网络请求失败: {e}")
return None
def get_device_info(self):
"""获取完整设备信息"""
try:
response = requests.get(f"{self.base_url}/info", timeout=10)
if response.status_code == 200:
data = response.json()
return data
else:
self.log_message(f"❌ 获取设备信息失败: HTTP {response.status_code}")
return None
except requests.exceptions.RequestException as e:
self.log_message(f"❌ 网络请求失败: {e}")
return None
def get_device_status(self):
"""获取设备状态"""
try:
response = requests.get(f"{self.base_url}/status", timeout=5)
if response.status_code == 200:
data = response.json()
return data
else:
self.log_message(f"❌ 获取设备状态失败: HTTP {response.status_code}")
return None
except requests.exceptions.RequestException as e:
self.log_message(f"❌ 网络请求失败: {e}")
return None
def register_device(self, server_url, device_name=None, location=None):
"""向远程服务器注册设备"""
try:
payload = {
"server_url": server_url,
"device_name": device_name or f"ESP32设备_{self.device_ip}",
"location": location or "未知位置"
}
response = requests.post(f"{self.base_url}/register",
json=payload, timeout=10)
if response.status_code == 200:
data = response.json()
return data
else:
self.log_message(f"❌ 设备注册失败: HTTP {response.status_code}")
return None
except requests.exceptions.RequestException as e:
self.log_message(f"❌ 网络请求失败: {e}")
return None
def display_device_info(self, info):
"""格式化显示设备信息"""
if not info:
return
print("\n" + "="*60)
print("🔍 ESP32设备硬件信息")
print("="*60)
# 基本标识信息
print(f"🆔 设备ID: {info.get('device_id', 'N/A')}")
print(f"📡 MAC地址: {info.get('mac_address', 'N/A')}")
print(f"🔢 数字ID: {info.get('numeric_id', 'N/A')} (0x{info.get('numeric_id', 0):08X})")
# 芯片信息
print(f"🔧 芯片型号: {info.get('chip_model', 'N/A')}")
print(f"📋 芯片版本: {info.get('chip_revision', 'N/A')}")
print(f"⚡ CPU核心: {info.get('chip_cores', 'N/A')}")
print(f"💾 Flash大小: {info.get('flash_size_bytes', 0) / (1024*1024):.1f} MB")
# 固件信息
print(f"🚀 项目名称: {info.get('project_name', 'N/A')}")
print(f"📦 固件版本: {info.get('firmware_version', 'N/A')}")
print(f"📅 编译日期: {info.get('compile_date', 'N/A')}")
print(f"⏰ 编译时间: {info.get('compile_time', 'N/A')}")
# 系统状态
uptime = info.get('uptime_seconds', 0)
hours = uptime // 3600
minutes = (uptime % 3600) // 60
seconds = uptime % 60
print(f"⏱️ 运行时间: {hours:02d}:{minutes:02d}:{seconds:02d}")
print(f"🧠 空闲内存: {info.get('free_heap_bytes', 0) / 1024:.1f} KB")
print("="*60)
print("✅ 所有ID均为芯片出厂烧录全球唯一")
print("="*60)
def main():
"""主函数 - 演示各种获取方式"""
print("🔍 ESP32设备ID获取工具")
print("=" * 50)
# 创建设备管理器
manager = ESP32DeviceManager("192.168.1.3") # 您的ESP32 IP地址
print("\n📋 方法1获取设备ID快速")
print("-" * 30)
device_id_info = manager.get_device_id()
if device_id_info:
print(f"🆔 设备ID: {device_id_info.get('device_id')}")
print(f"🔢 数字ID: {device_id_info.get('numeric_id')} (0x{device_id_info.get('numeric_id', 0):08X})")
print("\n📋 方法2获取完整设备信息")
print("-" * 30)
device_info = manager.get_device_info()
if device_info:
manager.display_device_info(device_info)
print("\n📋 方法3获取设备状态")
print("-" * 30)
device_status = manager.get_device_status()
if device_status:
print(f"🆔 设备ID: {device_status.get('device_id')}")
print(f"⏱️ 运行时间: {device_status.get('uptime_seconds')}")
print(f"🧠 空闲内存: {device_status.get('free_heap_bytes', 0) / 1024:.1f} KB")
print(f"📶 WiFi连接: {'✅ 已连接' if device_status.get('wifi_connected') else '❌ 未连接'}")
if device_status.get('wifi_connected'):
print(f"📡 WiFi SSID: {device_status.get('wifi_ssid', 'N/A')}")
print(f"📶 信号强度: {device_status.get('wifi_rssi', 'N/A')} dBm")
# 演示设备注册(可选)
print("\n📋 方法4设备注册演示")
print("-" * 30)
register_result = manager.register_device(
server_url="http://your-server.com/api/devices",
device_name="厨房热成像监控",
location="厨房"
)
if register_result:
print(f"✅ 设备注册成功: {register_result.get('message')}")
print(f"🆔 注册设备ID: {register_result.get('device_id')}")
def scan_devices():
"""扫描网络中的ESP32设备"""
print("\n🔍 扫描网络中的ESP32设备...")
print("-" * 40)
# 扫描常见的ESP32 IP范围
base_ip = "192.168.1."
found_devices = []
for i in range(1, 255):
ip = f"{base_ip}{i}"
try:
manager = ESP32DeviceManager(ip)
device_id_info = manager.get_device_id()
if device_id_info:
found_devices.append({
'ip': ip,
'device_id': device_id_info.get('device_id'),
'numeric_id': device_id_info.get('numeric_id')
})
print(f"✅ 发现设备: {ip} - ID: {device_id_info.get('device_id')}")
except:
pass # 忽略连接失败的IP
print(f"\n📊 扫描完成,发现 {len(found_devices)} 个ESP32设备")
return found_devices
if __name__ == "__main__":
try:
main()
# 可选:扫描网络设备
scan_choice = input("\n是否扫描网络中的其他ESP32设备(y/N): ")
if scan_choice.lower() == 'y':
scan_devices()
except KeyboardInterrupt:
print("\n⏹️ 程序被用户中断")
except Exception as e:
print(f"\n💥 程序异常: {str(e)}")