#!/usr/bin/env python3 """Поймать Beken-загрузчик модуля во время включения (через мост RT-4D, WSL/powershell). Формат флеша модуля = стандартный Beken (32+2 CRC), значит у него Beken UART-загрузчик, который слушает link-check КОРОТКОЕ окно после сброса. Этот тул одним процессом powershell в тайтовом цикле спамит link-check `01 E0 FC 01 00` и ловит ответ `04 0E 05 ...`. Использование: запусти тул, и в течение его работы ВЫКЛЮЧИ и включи рацию в режим «Обновление DMR чипа» (питание + MENU). Если поймаем ответ — загрузчик достижим через мост. ТОЛЬКО ЧТЕНИЕ/handshake — ни erase, ни write не шлём. """ import argparse, subprocess, sys PS = r''' $port="{port}"; $sec={sec} $p = New-Object System.IO.Ports.SerialPort $port,115200,"None",8,"one" $p.ReadTimeout=20; $p.WriteTimeout=50 try {{ $p.Open() }} catch {{ Write-Output "ERR:$($_.Exception.Message)"; exit }} $lc=[byte[]]@(1,224,252,1,0) # 01 E0 FC 01 00 $sw=[Diagnostics.Stopwatch]::StartNew() $hit=$false while($sw.Elapsed.TotalSeconds -lt $sec){{ try {{ $p.Write($lc,0,$lc.Length) }} catch {{}} Start-Sleep -Milliseconds 8 $n=$p.BytesToRead if($n -gt 0){{ $b=New-Object byte[] $n; $p.Read($b,0,$n)|Out-Null $hex=($b|ForEach-Object{{"{{0:x2}}"-f $_}}) -join "" if($hex -match "e0fc"){{ Write-Output ("HIT:"+$hex); $hit=$true; break }} else {{ Write-Output ("RX:"+$hex) }} }} }} $p.Close() if(-not $hit){{ Write-Output "NOHIT" }} ''' def main(): ap=argparse.ArgumentParser() ap.add_argument("--port", default="COM4") ap.add_argument("--sec", type=int, default=25) a=ap.parse_args() print(f"[спам link-check на {a.port} @115200, {a.sec}с]") print(">>> СЕЙЧАС выключи рацию и включи в режим «Обновление DMR чипа» (питание+MENU) <<<\n") r=subprocess.run(["powershell.exe","-NoProfile","-Command",PS.format(port=a.port,sec=a.sec)], capture_output=True, text=True) for line in r.stdout.replace("\r","").split("\n"): line=line.strip() if line.startswith("HIT:"): print(f"✅ ЗАГРУЗЧИК ОТВЕТИЛ: {line[4:]}") print(" -> Beken-загрузчик достижим через мост. Можно читать флеш.") elif line.startswith("RX:") and line[3:]: print(f" (эхо/данные: {line[3:][:60]})") elif line=="NOHIT": print("❌ Ответа загрузчика не поймано. Либо мост не пробрасывает загрузчик,") print(" либо окно/бод другие. Попробуй ещё раз или обсудим физ.доступ.") elif line.startswith("ERR:"): print(line) if __name__=="__main__": main()