<html>
<body>
<p class="font-claude-response-body break-words whitespace-normal …leading-[1.7]"><strong>Background</strong></p>
<p class="font-claude-response-body break-words whitespace-normal leading-[1.7]">Running WatchDogsGo on a uConsole CM4 with HackerGadgets AIO v1 with no ESP32/C5 available. Built a Python bridge script (<code class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]">wdg_wifi_bridge.py</code>) that emulates the projectZero serial protocol over a PTY, enabling full game functionality using the host's native Linux WiFi and Bluetooth adapters.</p>
[wdg_wifi_bridge.py](https://github.com/user-attachments/files/27095482/wdg_wifi_bridge.py)
<p class="font-claude-response-body break-words whitespace-normal leading-[1.7]"><strong>How it works</strong></p>
<p class="font-claude-response-body break-words whitespace-normal leading-[1.7]">The bridge creates a PTY at <code class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]">/tmp/esp32-pty</code> and symlinks it so the game can be launched with:</p>
<div role="group" aria-label="Code" tabindex="0" class="relative group/copy bg-bg-000/50 border-0.5 border-border-400 rounded-lg focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-100"><div class="sticky opacity-0 group-hover/copy:opacity-100 group-focus-within/copy:opacity-100 top-2 py-2 h-12 w-0 float-right"><div class="absolute right-0 h-8 px-2 items-center inline-flex z-10"><button class="inline-flex
items-center
justify-center
relative
isolate
shrink-0
can-focus
select-none
disabled:pointer-events-none
disabled:opacity-50
disabled:shadow-none
disabled:drop-shadow-none border-transparent
transition
font-base
duration-300
ease-[cubic-bezier(0.165,0.85,0.45,1)] h-8 w-8 rounded-md backdrop-blur-md _fill_10ocf_9 _ghost_10ocf_96" type="button" aria-label="Copy to clipboard" data-state="closed"><div class="relative"><div class="transition-all opacity-100 scale-100" style="width: 20px; height: 20px; display: flex; align-items: center; justify-content: center;"><svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg" class="transition-all opacity-100 scale-100" aria-hidden="true" style="flex-shrink: 0;"><path d="M12.5 3A1.5 1.5 0 0 1 14 4.5V6h1.5A1.5 1.5 0 0 1 17 7.5v8a1.5 1.5 0 0 1-1.5 1.5h-8A1.5 1.5 0 0 1 6 15.5V14H4.5A1.5 1.5 0 0 1 3 12.5v-8A1.5 1.5 0 0 1 4.5 3zm1.5 9.5a1.5 1.5 0 0 1-1.5 1.5H7v1.5a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5v-8a.5.5 0 0 0-.5-.5H14zM4.5 4a.5.5 0 0 0-.5.5v8a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5v-8a.5.5 0 0 0-.5-.5z"></path></svg></div><div class="absolute inset-0 flex items-center justify-center"><div class="transition-all opacity-0 scale-50" style="width: 20px; height: 20px; display: flex; align-items: center; justify-content: center;"><svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg" class="transition-all opacity-0 scale-50" aria-hidden="true" style="flex-shrink: 0;"><path d="M15.188 5.11a.5.5 0 0 1 .752.626l-.056.084-7.5 9a.5.5 0 0 1-.738.033l-3.5-3.5-.064-.078a.501.501 0 0 1 .693-.693l.078.064 3.113 3.113 7.15-8.58z"></path></svg></div></div></div></button></div></div><div class="overflow-x-auto"><pre class="code-block__code !my-0 !rounded-lg !text-sm !leading-relaxed p-3.5" style="color: rgb(234, 236, 240); background: transparent; font-family: var(--font-mono);"><code style="color: rgb(234, 236, 240); background: transparent; font-family: var(--font-mono); white-space: pre-wrap;"><span><span>sudo ./run.sh /tmp/esp32-pty</span></span></code></pre></div></div>
<p class="font-claude-response-body break-words whitespace-normal leading-[1.7]">It intercepts game serial commands and handles them natively on Linux:</p>
<div class="overflow-x-auto w-full px-2 mb-6">
Command | Handler
-- | --
scan_networks | iw dev wlan1 scan
scan_bt | bleak BLE scanner on hci adapter
start_sniffer | tcpdump in monitor mode → pcapng
start_handshake / start_handshake_serial | airodump-ng + hcxpcapngtool polling
</div>
<p class="font-claude-response-body break-words whitespace-normal leading-[1.7]"><strong>Hardware tested on</strong></p>
<ul class="[li_&]:mb-0 [li_&]:mt-1 [li_&]:gap-1 [&:not(:last-child)_ul]:pb-1 [&:not(:last-child)_ol]:pb-1 list-disc flex flex-col gap-1 pl-8 mb-3">
<li class="whitespace-normal break-words pl-2">uConsole CM4, HackerGadgets AIO v1</li>
<li class="whitespace-normal break-words pl-2">AC1200 WiFi card (wlan1) — wardriving + BLE</li>
<li class="whitespace-normal break-words pl-2">AWUS036ACM / MT7612U (wlan2) — packet sniff + HS capture</li>
<li class="whitespace-normal break-words pl-2">Internal UART Bluetooth (hci1) — BLE scanning</li>
</ul>
<p class="font-claude-response-body break-words whitespace-normal leading-[1.7]"><strong>HS Capture approach</strong></p>
<p class="font-claude-response-body break-words whitespace-normal leading-[1.7]"><code class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]">airodump-ng</code> handles the mt76x2u driver better than hcxdumptool on kernel 6.12.x (radiotap header compatibility). The bridge polls the capture file every 10 seconds with <code class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]">hcxpcapngtool</code> to detect new EAPOL/PMKID hashes and fires the game's handshake event (<code class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]">SSID:{name} AP:{bssid}</code>) which triggers 200 XP, the handshake_hunter badge, and map marker.</p>
<p class="font-claude-response-body break-words whitespace-normal leading-[1.7]"><strong>Systemd service</strong></p>
<div role="group" aria-label="ini code" tabindex="0" class="relative group/copy bg-bg-000/50 border-0.5 border-border-400 rounded-lg focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-100"><div class="sticky opacity-0 group-hover/copy:opacity-100 group-focus-within/copy:opacity-100 top-2 py-2 h-12 w-0 float-right"><div class="absolute right-0 h-8 px-2 items-center inline-flex z-10"><button class="inline-flex
items-center
justify-center
relative
isolate
shrink-0
can-focus
select-none
disabled:pointer-events-none
disabled:opacity-50
disabled:shadow-none
disabled:drop-shadow-none border-transparent
transition
font-base
duration-300
ease-[cubic-bezier(0.165,0.85,0.45,1)] h-8 w-8 rounded-md backdrop-blur-md _fill_10ocf_9 _ghost_10ocf_96" type="button" aria-label="Copy to clipboard" data-state="closed"><div class="relative"><div class="transition-all opacity-100 scale-100" style="width: 20px; height: 20px; display: flex; align-items: center; justify-content: center;"><svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg" class="transition-all opacity-100 scale-100" aria-hidden="true" style="flex-shrink: 0;"><path d="M12.5 3A1.5 1.5 0 0 1 14 4.5V6h1.5A1.5 1.5 0 0 1 17 7.5v8a1.5 1.5 0 0 1-1.5 1.5h-8A1.5 1.5 0 0 1 6 15.5V14H4.5A1.5 1.5 0 0 1 3 12.5v-8A1.5 1.5 0 0 1 4.5 3zm1.5 9.5a1.5 1.5 0 0 1-1.5 1.5H7v1.5a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5v-8a.5.5 0 0 0-.5-.5H14zM4.5 4a.5.5 0 0 0-.5.5v8a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5v-8a.5.5 0 0 0-.5-.5z"></path></svg></div><div class="absolute inset-0 flex items-center justify-center"><div class="transition-all opacity-0 scale-50" style="width: 20px; height: 20px; display: flex; align-items: center; justify-content: center;"><svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg" class="transition-all opacity-0 scale-50" aria-hidden="true" style="flex-shrink: 0;"><path d="M15.188 5.11a.5.5 0 0 1 .752.626l-.056.084-7.5 9a.5.5 0 0 1-.738.033l-3.5-3.5-.064-.078a.501.501 0 0 1 .693-.693l.078.064 3.113 3.113 7.15-8.58z"></path></svg></div></div></div></button></div></div><div class="text-text-500 font-small p-3.5 pb-0">ini</div><div class="overflow-x-auto"><pre class="code-block__code !my-0 !rounded-lg !text-sm !leading-relaxed p-3.5" style="color: rgb(234, 236, 240); background: transparent; font-family: var(--font-mono);"><code class="language-ini" style="color: rgb(234, 236, 240); background: transparent; font-family: var(--font-mono); white-space: pre;"><span><span class="token token section" style="color: rgb(211, 215, 222);">[</span><span class="token token section section-name" style="color: rgb(244, 123, 133);">Unit</span><span class="token token section" style="color: rgb(211, 215, 222);">]</span><span>
</span></span><span><span></span><span class="token token key" style="color: rgb(240, 117, 128);">Description</span><span class="token token" style="color: rgb(211, 215, 222);">=</span><span class="token token value" style="color: rgb(155, 233, 99);">WatchDogsGo WiFi + BLE Bridge</span><span>
</span></span><span><span></span><span class="token token key" style="color: rgb(240, 117, 128);">After</span><span class="token token" style="color: rgb(211, 215, 222);">=</span><span class="token token value" style="color: rgb(155, 233, 99);">network.target bluetooth.target</span><span>
</span></span><span>
</span><span><span></span><span class="token token section" style="color: rgb(211, 215, 222);">[</span><span class="token token section section-name" style="color: rgb(244, 123, 133);">Service</span><span class="token token section" style="color: rgb(211, 215, 222);">]</span><span>
</span></span><span><span></span><span class="token token key" style="color: rgb(240, 117, 128);">ExecStart</span><span class="token token" style="color: rgb(211, 215, 222);">=</span><span class="token token value" style="color: rgb(155, 233, 99);">/home/fusedstamen/python/WatchDogsGo/.venv/bin/python3 /home/fusedstamen/python/WatchDogsGo/wdg_wifi_bridge.py --iface wlan1 --bt-iface hci1 --sniffer-iface wlan2 --no-monitor --loot-dir /home/fusedstamen/python/WatchDogsGo/loot</span><span>
</span></span><span><span></span><span class="token token key" style="color: rgb(240, 117, 128);">Restart</span><span class="token token" style="color: rgb(211, 215, 222);">=</span><span class="token token value" style="color: rgb(155, 233, 99);">always</span><span>
</span></span><span><span></span><span class="token token key" style="color: rgb(240, 117, 128);">RestartSec</span><span class="token token" style="color: rgb(211, 215, 222);">=</span><span class="token token value" style="color: rgb(155, 233, 99);">3</span><span>
</span></span><span>
</span><span><span></span><span class="token token section" style="color: rgb(211, 215, 222);">[</span><span class="token token section section-name" style="color: rgb(244, 123, 133);">Install</span><span class="token token section" style="color: rgb(211, 215, 222);">]</span><span>
</span></span><span><span></span><span class="token token key" style="color: rgb(240, 117, 128);">WantedBy</span><span class="token token" style="color: rgb(211, 215, 222);">=</span><span class="token token value" style="color: rgb(155, 233, 99);">multi-user.target</span></span></code></pre></div></div>
<p class="font-claude-response-body break-words whitespace-normal leading-[1.7]"><strong>Notes</strong></p>
<ul class="[li_&]:mb-0 [li_&]:mt-1 [li_&]:gap-1 [&:not(:last-child)_ul]:pb-1 [&:not(:last-child)_ol]:pb-1 list-disc flex flex-col gap-1 pl-8 mb-3">
<li class="whitespace-normal break-words pl-2">You mentioned in issue #1 you'd consider landing a sanitised bridge script under <code class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]">extras/</code> with a proper security review pass — happy to work on that if useful</li>
<li class="whitespace-normal break-words pl-2">The script is in my fork at github.com/FusedStamen/WatchDogsGo</li>
<li class="whitespace-normal break-words pl-2">Dependencies: <code class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]">bleak</code>, <code class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]">airodump-ng</code>, <code class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]">hcxpcapngtool</code>, <code class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]">tcpdump</code>, <code class="bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]">iw</code></li></ul>
</body>
</html>