Skip to content

Production Tools

The Production Tools component provides 3 tools for factory device programming, parallel batch operations, and quality control testing. These tools are designed for production line workflows where multiple devices need consistent, verified firmware.


Execute a full factory programming pipeline on a single device: erase flash, flash bootloader, flash partition table, flash application firmware, and verify. Each step is tracked individually so failures can be diagnosed.

NameTypeDefaultDescription
program_configdict(required)Programming configuration (see fields below).
portstr | NoneNoneSerial port or socket:// URI. Required.
KeyTypeDefaultDescription
firmware_pathstr(required)Path to the main application binary.
addressstr"0x0"Flash address for the application binary.
erase_beforebooltrueErase entire flash before programming.
verifybooltrueVerify firmware after writing.
bootloaderstrNonePath to bootloader binary. Skipped if omitted.
bootloader_addressstr"0x1000"Flash address for the bootloader.
partition_tablestrNonePath to partition table binary. Skipped if omitted.
partition_table_addressstr"0x8000"Flash address for the partition table.
  1. Erase flash (if erase_before is true)
  2. Flash bootloader (if bootloader path is provided)
  3. Flash partition table (if partition_table path is provided)
  4. Flash application firmware (with optional verification)

Each step is executed sequentially. If any step fails, the pipeline stops and reports the failure along with all completed steps.

result = await client.call_tool("esp_factory_program", {
"program_config": {
"firmware_path": "/build/app.bin",
"address": "0x10000",
"erase_before": True,
"verify": True,
"bootloader": "/build/bootloader.bin",
"bootloader_address": "0x1000",
"partition_table": "/build/partitions.bin",
"partition_table_address": "0x8000"
},
"port": "/dev/ttyUSB0"
})
{
"success": true,
"port": "/dev/ttyUSB0",
"steps": [
{"step": "erase_flash", "success": true, "error": null},
{"step": "flash_bootloader", "address": "0x1000", "success": true, "error": null},
{"step": "flash_partition_table", "address": "0x8000", "success": true, "error": null},
{"step": "flash_firmware", "address": "0x10000", "success": true, "error": null}
],
"total_time_seconds": 28.45,
"firmware_path": "/build/app.bin",
"firmware_size_bytes": 524288
}

On step failure:

{
"success": false,
"error": "Firmware flash failed: Timeout after 300.0s",
"steps": [
{"step": "erase_flash", "success": true, "error": null},
{"step": "flash_bootloader", "address": "0x1000", "success": true, "error": null},
{"step": "flash_partition_table", "address": "0x8000", "success": true, "error": null},
{"step": "flash_firmware", "address": "0x10000", "success": false, "error": "Timeout after 300.0s"}
],
"port": "/dev/ttyUSB0"
}

Program multiple devices concurrently with the same firmware. Each device goes through the full factory programming pipeline (erase, flash, verify) in parallel using asyncio.gather.

NameTypeDefaultDescription
device_listlist[str](required)List of serial ports to program (e.g., ["/dev/ttyUSB0", "/dev/ttyUSB1"]).
firmware_pathstr(required)Path to the firmware binary. Same firmware is flashed to all devices.
result = await client.call_tool("esp_batch_program", {
"device_list": ["/dev/ttyUSB0", "/dev/ttyUSB1", "/dev/ttyUSB2"],
"firmware_path": "/build/production_app.bin"
})
{
"success": true,
"total_devices": 3,
"succeeded": 3,
"failed": 0,
"total_time_seconds": 32.15,
"firmware_path": "/build/production_app.bin",
"devices": [
{"port": "/dev/ttyUSB0", "success": true, "error": null, "time_seconds": 28.45},
{"port": "/dev/ttyUSB1", "success": true, "error": null, "time_seconds": 30.12},
{"port": "/dev/ttyUSB2", "success": true, "error": null, "time_seconds": 32.15}
]
}

The top-level success is true only when all devices succeed. Individual device results are always reported in the devices array regardless of outcome.


Run quality control tests on a connected device. The basic test suite verifies chip identification, flash identification, and MAC address readability. The extended suite adds a flash read/write connectivity test.

NameTypeDefaultDescription
portstr | NoneNoneSerial port or socket:// URI. Required.
test_suitestr"basic"Test suite to run: "basic" or "extended".
TestCommandChecks
Chip identificationchip-idChip type and ID
Flash identificationflash-idManufacturer and flash size
MAC addressread-macFactory MAC address
result = await client.call_tool("esp_quality_control", {
"port": "/dev/ttyUSB0",
"test_suite": "extended"
})
{
"success": true,
"port": "/dev/ttyUSB0",
"test_suite": "extended",
"verdict": "PASS",
"tests_run": 4,
"tests_passed": 4,
"tests_failed": 0,
"total_time_seconds": 6.82,
"tests": [
{
"test": "chip_identification",
"success": true,
"chip": "ESP32-S3",
"chip_id": "0x00f01d83"
},
{
"test": "flash_identification",
"success": true,
"manufacturer": "0xef",
"flash_size": "4MB"
},
{
"test": "mac_address",
"success": true,
"mac": "aa:bb:cc:dd:ee:ff"
},
{
"test": "flash_read_4kb",
"success": true,
"bytes_read": 4096,
"has_data": true,
"non_erased_bytes": 3841
}
]
}

The verdict field is "PASS" when all tests succeed and "FAIL" when any test fails. Individual test results are always included in the tests array.