"""Identity/hash-gated application DFU on selected four TXs plus V4 bench RX.""" import hashlib import io import json from pathlib import Path import subprocess import time import zipfile from profile_four_tx_fixture import TXS,RX,resolve from profile_switch import exchange,open_session import serial from serial.tools import list_ports ROOT=Path(__file__).resolve().parent REPORT=ROOT/'deployment.json' if REPORT.exists(): raise RuntimeError('A deployment report already exists; no implicit reflashing') manifest=json.loads((ROOT/'manifest.json').read_text()) report={'complete':False,'tx':[],'rx':{},'services_before':{}} def save():REPORT.write_text(json.dumps(report,indent=2)+'\n') def run(args,timeout=120): p=subprocess.run([str(a) for a in args],capture_output=True,text=True,timeout=timeout) print(json.dumps({'command':args,'rc':p.returncode,'out':p.stdout,'err':p.stderr},default=str),flush=True) if p.returncode:raise RuntimeError('Operation failed: '+str(args[0])) return p.stdout+p.stderr def service(name,action):run(['sudo','-n','systemctl',action,name],20) def boot_port(t): port=resolve(t) p=next(p for p in list_ports.comports() if p.device==port) if (p.vid,p.pid)==(t['boot_vid'],t['boot_pid']):return port if p.vid!=0x239A or p.pid not in (0x8029,0x4405): raise RuntimeError('Neither identified application nor identified UF2 bootloader') # Enter immediately before this board's DFU, rather than assuming it stayed # in recovery while the other images were built/transferred. try: with serial.Serial(port,115200,timeout=.2,write_timeout=2) as stream: stream.dtr=True if t['channel']!=2: stream.write(b'+++MESHCORE-TERM-STOP\r\n+++MESHCORE-TERM-START\r\n') stream.flush();time.sleep(.7);stream.reset_input_buffer() stream.write(b'uf2reset\r\n');stream.flush();time.sleep(.7) except (OSError,serial.SerialException):pass deadline=time.monotonic()+20 while time.monotonic()