Switch from NimBLE-Arduino to ESP32-BLE-MIDI library

Replace direct NimBLE-Arduino dependency with max22/ESP32-BLE-MIDI
wrapper library (v0.3.2). Rewrite ble_midi_transport to use
BLEMidiServer API instead of raw NimBLEDevice calls.

Removes patch_nimble_device() from pre_build.py — no longer needed
since BT controller init is managed by the library internally.

The library uses NimBLE v1.4.1 internally and configures advertising
without setScanResponse() or setName(), which may resolve the invisible
BLE advertising issue on ESP32-S3.
This commit is contained in:
ash
2026-07-01 06:34:36 +00:00
parent 1517eda13e
commit 62d1e430d5
4 changed files with 67 additions and 276 deletions
+5 -92
View File
@@ -70,8 +70,10 @@ def patch_sdkconfig_bt():
content = f.read()
defines = {
"CONFIG_BT_ENABLED": 1,
"CONFIG_BT_NIMBLE_ENABLED": 1,
# Do NOT set CONFIG_BT_ENABLED here — forces Arduino framework
# to pre-init BT controller at startup, which conflicts with
# TinyUSB on ESP32-S3 (causes reboot on USB MIDI send).
# NimBLEDevice::init() handles its own init.
"CONFIG_BTDM_CTRL_MODE_BLE_ONLY": 1,
"CONFIG_BT_NIMBLE_MAX_CONNECTIONS": 1,
"CONFIG_BT_NIMBLE_TASK_STACK_SIZE": 6144,
@@ -160,95 +162,6 @@ def patch_nimconfig():
print("nimconfig.h patched successfully")
def patch_nimble_device():
# Find NimBLEDevice.cpp in the NimBLE-Arduino library
search_dirs = [
os.path.join(os.getcwd(), ".pio", "libdeps"),
os.path.expanduser("~/.platformio/lib"),
]
for env_dir in ["esp32s3", ""]:
candidate = os.path.join(
os.getcwd(), ".pio", "libdeps",
env_dir, "NimBLE-Arduino", "src", "NimBLEDevice.cpp"
) if env_dir else ""
if candidate and os.path.exists(candidate):
dev_path = candidate
break
else:
dev_path = None
for base in search_dirs:
if not os.path.exists(base):
continue
for root, _dirs, files in os.walk(base):
if "NimBLEDevice.cpp" in files:
dev_path = os.path.join(root, "NimBLEDevice.cpp")
break
if dev_path:
break
if not dev_path:
print("WARNING: NimBLEDevice.cpp not found, skipping controller init patch")
return
print(f"Patching {dev_path} to handle double BT controller init")
with open(dev_path, 'r') as f:
content = f.read()
# Replace the ESP_ERROR_CHECK(esp_bt_controller_init) block to handle
# ESP_ERR_INVALID_STATE (already initialized by Arduino framework when CONFIG_BT_ENABLED)
old_block = (
' ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg));\n'
' ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE));\n'
' ESP_ERROR_CHECK(esp_nimble_hci_init());'
)
new_block = (
' if (esp_bt_controller_init(&bt_cfg) == ESP_OK) {\n'
' ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE));\n'
' }\n'
' ESP_ERROR_CHECK(esp_nimble_hci_init());'
)
if old_block in content:
content = content.replace(old_block, new_block)
with open(dev_path, 'w') as f:
f.write(content)
print(" Patched esp_bt_controller_init to skip if already initialized")
else:
# Try alternative indentation (1 tab = 8 spaces)
old_block_alt = old_block.replace(' ', '\t')
new_block_alt = new_block.replace(' ', '\t')
if old_block_alt in content:
content = content.replace(old_block_alt, new_block_alt)
with open(dev_path, 'w') as f:
f.write(content)
print(" Patched (tab-indented) esp_bt_controller_init")
else:
# Try with partial indentation
patterns = [
(r'(\s*)ESP_ERROR_CHECK\(esp_bt_controller_init\(&bt_cfg\)\);\s*\n'
r'\1ESP_ERROR_CHECK\(esp_bt_controller_enable\(ESP_BT_MODE_BLE\)\);\s*\n'
r'\1ESP_ERROR_CHECK\(esp_nimble_hci_init\(\)\);'),
]
for pattern in patterns:
replacement = (
r'\1if (esp_bt_controller_init(&bt_cfg) == ESP_OK) {\n'
r'\1 ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE));\n'
r'\1}\n'
r'\1ESP_ERROR_CHECK(esp_nimble_hci_init());'
)
new_content = re.sub(pattern, replacement, content)
if new_content != content:
content = new_content
with open(dev_path, 'w') as f:
f.write(content)
print(" Patched esp_bt_controller_init (regex)")
break
else:
print(" WARNING: Could not find esp_bt_controller_init pattern in NimBLEDevice.cpp")
patch_usb_ids()
patch_sdkconfig_bt()
patch_nimconfig()
patch_nimble_device()
patch_nimconfig()