UART-controlled ESP32 peripheral for automated E2E Bluetooth testing. Dual-mode (Classic BT + BLE) via Bluedroid on original ESP32. Firmware (ESP-IDF v5.x, 2511 lines C): - NDJSON protocol over UART1 (115200 baud) - System commands: ping, reset, get_info, get_status - Classic BT: GAP, SPP, all 4 SSP pairing modes - BLE: GATTS, advertising, GATT service/characteristic management - 6 device personas: headset, speaker, keyboard, sensor, phone, bare - Event reporter: thread-safe async event queue to host Python MCP server (FastMCP, 1626 lines): - Async serial client with command/response correlation - Event queue with wait_for pattern matching - Tools: connection, configure, classic, ble, persona, events - MCP resources: esp32://status, esp32://events, esp32://personas Tests: 74 unit tests passing, 5 integration test stubs (skip without hardware)
52 lines
1.2 KiB
TOML
52 lines
1.2 KiB
TOML
[project]
|
|
name = "mcbluetooth-esp32"
|
|
version = "2026.02.02"
|
|
description = "ESP32 Bluetooth test harness MCP server — UART-controlled peripheral for E2E Bluetooth testing"
|
|
requires-python = ">=3.11"
|
|
license = {text = "MIT"}
|
|
authors = [{name = "Ryan Malloy", email = "ryan@supported.systems"}]
|
|
keywords = ["bluetooth", "esp32", "mcp", "testing", "ble", "ssp"]
|
|
classifiers = [
|
|
"Development Status :: 3 - Alpha",
|
|
"Intended Audience :: Developers",
|
|
"Programming Language :: Python :: 3.11",
|
|
"Programming Language :: Python :: 3.12",
|
|
"Programming Language :: Python :: 3.13",
|
|
"Topic :: Software Development :: Testing",
|
|
"Topic :: System :: Hardware",
|
|
]
|
|
|
|
dependencies = [
|
|
"fastmcp>=2.14.4",
|
|
"pyserial-asyncio>=0.6",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
dev = [
|
|
"pytest>=8.0",
|
|
"pytest-asyncio>=0.24",
|
|
"ruff>=0.8",
|
|
]
|
|
|
|
[project.scripts]
|
|
mcbluetooth-esp32 = "mcbluetooth_esp32:main"
|
|
|
|
[build-system]
|
|
requires = ["hatchling"]
|
|
build-backend = "hatchling.build"
|
|
|
|
[tool.hatch.build.targets.wheel]
|
|
packages = ["src/mcbluetooth_esp32"]
|
|
|
|
[tool.ruff]
|
|
line-length = 100
|
|
target-version = "py311"
|
|
|
|
[tool.ruff.lint]
|
|
select = ["E", "F", "W", "I", "B", "UP"]
|
|
ignore = ["E501"]
|
|
|
|
[tool.pytest.ini_options]
|
|
asyncio_mode = "auto"
|
|
testpaths = ["tests"]
|