ワンクリックで
upy-deploy
第五步——一键烧录运行。上传 firmware/ 到设备、软复位、持久会话采集输出、读取设备端日志、初判通过/失败。触发:upy-generate 完成后自动进入。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
第五步——一键烧录运行。上传 firmware/ 到设备、软复位、持久会话采集输出、读取设备端日志、初判通过/失败。触发:upy-generate 完成后自动进入。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
| name | upy-deploy |
| description | 第五步——一键烧录运行。上传 firmware/ 到设备、软复位、持久会话采集输出、读取设备端日志、初判通过/失败。触发:upy-generate 完成后自动进入。 |
给定 project-manifest.json(phase: generate),将 firmware/ 上传到 MicroPython 设备、运行、采集输出、初判结果。不做错误修复(那是 upy-autofix 的职责)。
python --version
mpremote --version
依赖:Python 3 标准库 + mpremote。
upy-generate Phase 5 约束 #0 要求 main.py 第一行代码是 time.sleep(3)。这给了 deploy 软复位后足够的重连时间:
mpremote soft-reset
→ 设备重启,USB 断开
→ Windows 重新枚举 COM(1~3s)
→ mpremote 重连 + resume
→ main.py 恰好在 3s 延时窗口内,此时连上不会丢任何输出
没有这个延时,mpremote 连上时 main.py 可能已经跑了一半(日志头、I2C 扫描结果丢失)。
deploy 从两个来源获取设备输出:
| 来源 | 方式 | 特点 |
|---|---|---|
| REPL 实时输出 | mpremote 持久会话 | print() 即时可见,但 REPL 断开即丢失 |
| 设备端日志文件 | mpremote fs cp :log/run_*.log | 跨重启保留,REPL 断开仍可读取 |
deploy Phase 5 抓取日志文件作为补充——即使持久会话因断连遗漏了部分输出,日志文件能补全。
首选方案:使用项目自带的 tools/flash_device.py(由 upy-scaffold 生成):
# 编译 .py → .mpy(排除 main.py/boot.py)+ 上传,--no-reset 让 deploy 自己控制复位时机
python tools/flash_device.py --compile --upload --no-reset --port <COM>
flash_device.py 自动完成:递归遍历 firmware/、跳过 .gitkeep、创建远程目录、逐文件 cp、main.py 排到最后上传。
降级方案(tools/flash_device.py 不存在时,直接用 mpremote):
cd firmware
# 1. 创建必要目录(先 ls 检查是否已存在)
mpremote connect <device> resume fs ls :log >/dev/null 2>&1 || \
mpremote connect <device> resume fs mkdir :log
mpremote connect <device> resume fs ls :lib >/dev/null 2>&1 || \
mpremote connect <device> resume fs mkdir :lib
mpremote connect <device> resume fs ls :drivers >/dev/null 2>&1 || \
mpremote connect <device> resume fs mkdir :drivers
mpremote connect <device> resume fs ls :tasks >/dev/null 2>&1 || \
mpremote connect <device> resume fs mkdir :tasks
# 2. 上传 lib/ 和 drivers/(先传依赖,后传入口)
for f in lib/**/*.py; do
mpremote connect <device> resume fs cp "$f" ":$f"
sleep 0.5
done
for f in drivers/**/*.py; do
mpremote connect <device> resume fs cp "$f" ":$f"
sleep 0.5
done
# 3. 上传配置和任务文件
mpremote connect <device> resume fs cp board.py :board.py
mpremote connect <device> resume fs cp conf.py :conf.py
mpremote connect <device> resume fs cp boot.py :boot.py
for f in tasks/*.py; do
mpremote connect <device> resume fs cp "$f" ":$f"
sleep 0.5
done
# 4. main.py 最后上传(它一旦存在,设备启动就会执行)
mpremote connect <device> resume fs cp main.py :main.py
上传顺序:lib/ → drivers/ → config → tasks → main.py(最后)。flash_device.py 通过排序保证此顺序。
从 firmware/ 目录执行:cd firmware 后所有路径为相对路径,远程路径(: 前缀)与本地路径一致,避免多一层 firmware/ 目录前缀。
关于 resume:降级方案中 fs cp 必须带 resume。flash_device.py 在 upload 阶段设备空闲,实测不加 resume 也可正常工作。
# 列出设备文件树
mpremote connect <device> resume fs tree
# 或逐目录对比
mpremote connect <device> resume fs ls :lib/
mpremote connect <device> resume fs ls :drivers/
对比本地文件列表,缺文件则重传。
# 不使用 resume —— 就是要让设备重启
mpremote connect <device> soft-reset
调用 wait_for_device(com, timeout=60) —— 轮询直到设备应答:
每 2 秒:
mpremote connect <com> resume exec "print(1)"
→ 成功(收到 "1"): 设备就绪,main.py 正在 3s 延时窗口内
→ 失败(连接错误/无应答): 继续等待
→ 超时 60s: 报 FAIL,终止
注意:soft-reset 后设备重启,Windows 可能换 COM 号。如果 connect <com> 持续失败,用 mpremote connect list 重新扫描 COM 口。
设备自动运行 main.py。建立持久会话捕获完整输出(60s 超时)。
Windows(subprocess + pipe):
import subprocess, threading, time
proc = subprocess.Popen(
["mpremote", "connect", com, "resume", "repl"],
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, bufsize=0,
)
output_lines = []
def reader():
for line in iter(proc.stdout.readline, b""):
text = line.decode("utf-8", errors="replace")
output_lines.append(text)
print(text, end="") # 实时回显
t = threading.Thread(target=reader, daemon=True)
t.start()
# 等待 60s 或 scheduler 稳定运行标志
deadline = time.time() + 60
while time.time() < deadline:
if any("starting scheduler" in l.lower() for l in output_lines):
break # 调度器启动 = 成功,提前结束
time.sleep(1)
proc.terminate()
Linux/macOS(PTY,参见 mpremote-live-session):
使用 pty.openpty() + os.fork() 建立真正的终端会话。比 pipe 更可靠,支持 Ctrl+C 转发。
超时策略:
"starting scheduler" 或等效标志 → 提前判定 PASS,结束采集持久会话可能因断连丢失部分输出。从设备文件系统补充读取。
获取日志目录:从 firmware/conf.py 读取 LOG_DIR,默认 /log:
LOG_DIR=$(python -c "import sys; sys.path.insert(0,'firmware'); from conf import LOG_DIR; print(LOG_DIR)" 2>/dev/null || echo "/log")
5a. 即时分析(fs cat → pipe 到 log_report.py):
python tools/read_device_log.py --port <COM> --log-dir $LOG_DIR \
| python tools/log_report.py --input > deploy_log_report.json
read_device_log.py 内部用 fs ls :{log_dir}/ 动态发现所有 run_*.log,然后 fs cat 逐文件读取内容输出到 stdout。log_report.py 接收 stdin,输出结构化 JSON。
5b. 下载原始文件(fs cp → 本地,供 autofix 用):
python tools/read_device_log.py --port <COM> --log-dir $LOG_DIR --download ./deploy_logs/
fs cp 下载每个 run_*.log 到本地 deploy_logs/ 目录。这些原始 .log 文件在 FAIL 时传给 upy-autofix 的服务端 LLM 做深度分析。
降级方案(tools/read_device_log.py 不存在时):
mpremote connect <device> resume fs ls :log/
mpremote connect <device> resume fs cp :log/run_0.log deploy_log_0.log
mpremote connect <device> resume fs cp :log/run_1.log deploy_log_1.log
# ... 按 fs ls 实际列出的文件逐一下载
python tools/log_report.py deploy_log_*.log
日志文件包含从 boot 到 crash 的完整记录(即使 REPL 断开也保留),是判断失败原因的关键数据源。
纯本地规则,不调服务端 AI。 结合两个数据源做判定:
数据源 1 — REPL 实时输出(grep 规则):
判定规则:
output 含 "Traceback (most recent call last)" → FAIL (Python 异常)
output 含 "rst cause:" → FAIL (硬件复位)
output 含 "Guru Meditation Error" → FAIL (ESP32 内核 panic)
output 含 "MemoryError" / "ENOMEM" → FAIL (内存不足)
60s 内无任何输出 → FAIL (设备无响应)
其他 → PASS ✓
数据源 2 — deploy_log_report.json(log_report.py 结构化输出):
# 检查 JSON 中的 error_count
error_count=$(python -c "import json; print(json.load(open('deploy_log_report.json'))['error_count'])")
若 error_count > 0 且 REPL grep 未命中 → 仍判定 FAIL(日志中有错误,但 REPL 输出可能因断连丢失)。逐一检查 error level:P0 和 P1 级别直接 FAIL,P2 级别作为辅助信息。
输出结构:
{ status: "PASS" | "FAIL",
com_port: "COM3",
output: <采集的完整 REPL 输出>,
log_report: <deploy_log_report.json 内容>,
log_files: <deploy_logs/ 目录下的原始 .log 文件列表>,
deployed_files: <fs tree 输出>,
device_info: { firmware, flash_free, freq }
}
PASS → 流程结束,展示运行结果。 FAIL → 将完整上下文(REPL 输出 + deploy_log_report.json + deploy_logs/*.log)传给 upy-autofix。
| Windows | macOS | Linux | |
|---|---|---|---|
| 端口标识 | COM3 | /dev/tty.usbmodem* | /dev/serial/by-id/* 或 mpy-dev tty |
| 持久会话 | subprocess + pipe | PTY | PTY |
| 端口变化处理 | mpremote connect list 重扫 | 路径稳定(USB 槽位不变) | mpy-dev 按设备名查找 |
| 重连等待 | 是(COM 号可能变) | 通常不需要 | 不需要(by-id 稳定) |
| 步骤 | 首选工具 | 备用 skill | 说明 |
|---|---|---|---|
| 上传文件 | tools/flash_device.py --upload --no-reset | mpremote-file-transfer | 项目自带工具,递归上传 + 排序 main.py 最后 |
| 校验文件 | — | mpremote-device-interaction | fs tree / fs ls 对比本地文件列表 |
| 软复位 | — | mpremote-device-interaction | soft-reset(不用 resume) |
| 重连等待 | — | mpremote-device-interaction | resume exec "print(1)" 轮询 |
| 持久会话 | — | mpremote-live-session | PTY/pipe 采集完整 REPL 输出 |
| 抓日志 cat | tools/read_device_log.py --port | mpremote-file-transfer | fs cat 读内容 pipe 到 log_report.py |
| 抓日志 cp | tools/read_device_log.py --download | mpremote-file-transfer | fs cp 下载原始 .log 供 autofix |
| 日志解析 | tools/log_report.py --input | — | 结构化 JSON(P0~P2 分级 + MemoryError/ENOMEM) |
upy-generate:输入完整 firmware/ + manifest(phase: generate)upy-autofix:FAIL 时传入错误上下文upy-wiring / upy-diagram:并行生成可视化(不阻塞 deploy)Analyze MicroPythonOS App ideas directly or when invoked by mpos-plan-app. Use to turn natural-language MPOS App requests into requirements, default app identity, manifest draft, Activity/Service plan, MPOS/LVGL API plan, dependency risk, test/deploy plan, mandatory MicroPythonOS resource links, and a JSON handoff before code generation.
Deploy or preview a MicroPythonOS app on desktop, web, device copy, MPK install, or installer/flash guidance paths. Use when Codex needs to launch a confirmed app for manual preview, copy it to a board with mpremote, validate an MPK on-device, or route firmware install and erase to install.micropythonos.com. Does not own app generation, static lint, packaging, or default smoke testing.
MicroPythonOS 基础开发知识库。提供代码架构、App/MPK 约束、LVGL 编程约定、MPY API reference、官方 docs 专题 reference、AGENTS 本地强约束。mpos-plan-app / mpos-analyze-app / mpos-prepare-deps / mpos-gen-app / mpos-test-app / mpos-package-app / mpos-deploy-app / mpos-publish-app 均依赖此 skill。
Generate, update, and repeatedly repair MicroPythonOS App code after requirements are confirmed. Use after mpos-analyze-app and optionally mpos-prepare-deps to create or modify an internal_filesystem/apps package directory with root MANIFEST.JSON, root icon_64x64.png, assets/*.py entrypoints/dependencies, dependency adapters, and validation results. Always defaults to a two-phase flow: first produce a generation plan and ask for confirmation, then write files only after explicit user confirmation. Supports repeated calls for user feature changes and test-failure repair loops. Does not analyze vague requirements, prepare external dependencies, package MPK files, deploy devices, flash firmware, publish to upystore, or rebuild lvgl_micropython.
Package and validate a single MicroPythonOS App as an MPK release artifact. Use when Codex needs to create a .mpk, validate an MPOS App manifest/icon/package structure, emit one app_index_entry.json fragment, run optional temporary install validation, or prepare AppStore/upystore publishing artifacts without uploading.
Orchestrate a MicroPythonOS App workflow across analyze, dependency preparation, generation, testing, packaging, deployment, and upystore publishing. Use when Codex needs to start from a natural-language app request, continue or resume an interrupted MPOS app task, decide the next mpos-* skill, maintain per-app plan_state.json and activity_log.jsonl under tmp/mpos-plan-app, handle user requirement changes with invalidation confirmation, or run the default path through mpos-publish-app. Does not implement code, download dependencies, test, package, deploy, flash, or upload directly.