Add pre-flash firmware backup step with restore instructions

This commit is contained in:
justin committed 2026-05-09 17:34:52 -07:00
1 parent 0fa657544c
commit cb7f013fac
1 file changed
+59
+59
View File
@@ -8,6 +8,7 @@ import glob
import importlib.util import importlib.util
import argparse import argparse
import inspect import inspect
import datetime
REPO_URL = "https://github.com/crosspoint-reader/crosspoint-reader.git" REPO_URL = "https://github.com/crosspoint-reader/crosspoint-reader.git"
REPO_DIR = "crosspoint-reader" REPO_DIR = "crosspoint-reader"
@@ -63,6 +64,63 @@ def get_local_head_sha():
return None return None
def backup_device():
print(" Backup your current firmware before flashing? [y/N]: ", end="", flush=True)
answer = input().strip().lower()
if answer not in ("y", "yes"):
print(" Skipping backup.")
return
print()
print(" Ensure your xteink device is connected via USB and awake.")
input(" Press Enter when ready... ")
ports = detect_serial_ports()
if not ports:
print(" No USB serial ports detected — skipping backup.")
return
cu_ports = [(d, desc) for d, desc in ports if d.startswith("/dev/cu.")]
recommended = cu_ports[0][0] if cu_ports else ports[0][0]
print(f"\n Found {len(ports)} serial port(s):")
for i, (device, desc) in enumerate(ports, 1):
tag = " ← recommended" if device == recommended else ""
print(f" {i}. {device} — {desc}{tag}")
choice = input(f"\n Press ENTER to use {recommended}, or enter 1-{len(ports)}: ").strip()
if not choice:
port = recommended
elif choice.isdigit() and 0 <= int(choice) - 1 < len(ports):
port = ports[int(choice) - 1][0]
else:
print(" Invalid choice — skipping backup.")
return
timestamp = datetime.datetime.now().strftime("%Y%m%d.%H%M%S")
filename = f"backup.{timestamp}.bin"
print(f"\n Reading flash from {port} → {filename} ...")
result = subprocess.run(
f"esptool --port {port} read-flash 0x0 ALL {filename}",
shell=True,
)
if result.returncode == 0:
print(f" ✓ Backup saved to {filename}")
print()
print(f" To restore your device to this backup, run:")
print(f" esptool --port {port} write-flash 0x0 {filename}")
else:
print(" ✗ Backup failed. You can continue or abort and retry manually.")
if input(" Continue without backup? [y/N]: ").strip().lower() not in ("y", "yes"):
print(" Aborted.")
sys.exit(0)
print()
def clone_repo(force: bool = True): def clone_repo(force: bool = True):
print("[1/3] Preparing CrossPoint repository...") print("[1/3] Preparing CrossPoint repository...")
@@ -313,6 +371,7 @@ def main():
print(" Aborted.") print(" Aborted.")
sys.exit(0) sys.exit(0)
print() print()
backup_device()
clone_repo(force=not args.no_reclone) clone_repo(force=not args.no_reclone)
clear_plugin_caches() clear_plugin_caches()
apply_plugins(yes_all=args.yes) apply_plugins(yes_all=args.yes)