306 lines
14 KiB
HTML
306 lines
14 KiB
HTML
|
|
<!DOCTYPE html>
|
||
|
|
<html lang="en">
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
||
|
|
<meta name="theme-color" content="#0a0e17">
|
||
|
|
<title>FlipperDroid</title>
|
||
|
|
<link rel="stylesheet" href="/css/style.css">
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<div class="app">
|
||
|
|
|
||
|
|
<div class="header">
|
||
|
|
<div class="header-icon">
|
||
|
|
<svg viewBox="0 0 24 24"><path d="M20 2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-8 2c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z"/></svg>
|
||
|
|
</div>
|
||
|
|
<h1>FlipperDroid</h1>
|
||
|
|
<p id="status-badge">Detecting Flipper...</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="status-bar">
|
||
|
|
<div class="status-chip" id="chip-conn"><span class="dot off"></span> LINK</div>
|
||
|
|
<div class="status-chip" id="chip-gpio"><span class="dot off"></span> GPIO</div>
|
||
|
|
<div class="status-chip" id="chip-rf"><span class="dot off"></span> RF</div>
|
||
|
|
<div class="status-chip" id="chip-nfc"><span class="dot off"></span> NFC</div>
|
||
|
|
<div class="status-chip" id="chip-cpu"><span class="dot off"></span> CPU</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- ==================== DASHBOARD ==================== -->
|
||
|
|
<div class="page active" id="page-dashboard">
|
||
|
|
<div class="section">
|
||
|
|
<div class="section-title">Connection</div>
|
||
|
|
<div class="card">
|
||
|
|
<div class="info-grid">
|
||
|
|
<div class="info-cell"><div class="info-label">Status</div><div class="info-value" id="info-status">-</div></div>
|
||
|
|
<div class="info-cell"><div class="info-label">Transport</div><div class="info-value" id="info-transport">-</div></div>
|
||
|
|
<div class="info-cell"><div class="info-label">Device</div><div class="info-value" id="info-device">-</div></div>
|
||
|
|
<div class="info-cell"><div class="info-label">Product</div><div class="info-value" id="info-product">-</div></div>
|
||
|
|
<div class="info-cell"><div class="info-label">Serial</div><div class="info-value" id="info-serial">-</div></div>
|
||
|
|
<div class="info-cell"><div class="info-label">Firmware</div><div class="info-value" id="info-firmware">-</div></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="card" style="margin-top:12px">
|
||
|
|
<div class="card-row">
|
||
|
|
<div class="card-row-info">
|
||
|
|
<div class="card-row-label">Auto-Connect</div>
|
||
|
|
<div class="card-row-desc">Reconnect to Flipper on boot and disconnect</div>
|
||
|
|
</div>
|
||
|
|
<label class="toggle"><input type="checkbox" id="toggle-autoconnect" onchange="setConfig('AUTO_CONNECT', this.checked?1:0)"><span class="toggle-slider"></span></label>
|
||
|
|
</div>
|
||
|
|
<div class="card-row">
|
||
|
|
<div class="card-row-info">
|
||
|
|
<div class="card-row-label">CPU Sharing</div>
|
||
|
|
<div class="card-row-desc">Let Flipper offload compute to phone CPU</div>
|
||
|
|
</div>
|
||
|
|
<label class="toggle"><input type="checkbox" id="toggle-cpushare" onchange="setConfig('CPU_SHARE', this.checked?1:0)"><span class="toggle-slider"></span></label>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<button class="btn" onclick="reconnect()">Reconnect</button>
|
||
|
|
<button class="btn btn-secondary" onclick="pingFlipper()">Ping</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- ==================== GPIO ==================== -->
|
||
|
|
<div class="page" id="page-gpio">
|
||
|
|
<div class="section">
|
||
|
|
<div class="section-title">GPIO Control</div>
|
||
|
|
<div class="card">
|
||
|
|
<div class="gpio-grid" id="gpio-grid"></div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="card" style="margin-top:12px">
|
||
|
|
<div class="section-title">Quick Actions</div>
|
||
|
|
<div class="card-row">
|
||
|
|
<select id="gpio-pin" class="input-select">
|
||
|
|
<option value="2">PA2</option><option value="3">PA3</option>
|
||
|
|
<option value="4">PA4</option><option value="6">PA6</option>
|
||
|
|
<option value="7">PA7</option><option value="13">PB2</option>
|
||
|
|
<option value="14">PB3</option><option value="15">PB13</option>
|
||
|
|
<option value="16">PB14</option><option value="17">PC0</option>
|
||
|
|
<option value="18">PC1</option><option value="19">PC3</option>
|
||
|
|
</select>
|
||
|
|
<select id="gpio-mode" class="input-select">
|
||
|
|
<option value="0">Input</option>
|
||
|
|
<option value="1">Output Push-Pull</option>
|
||
|
|
<option value="2">Output Open-Drain</option>
|
||
|
|
<option value="3">Analog</option>
|
||
|
|
</select>
|
||
|
|
<button class="btn btn-small" onclick="gpioInit()">Init</button>
|
||
|
|
</div>
|
||
|
|
<div class="card-row">
|
||
|
|
<button class="btn btn-small" onclick="gpioRead()">Read</button>
|
||
|
|
<button class="btn btn-small" onclick="gpioWrite(1)">HIGH</button>
|
||
|
|
<button class="btn btn-small btn-danger" onclick="gpioWrite(0)">LOW</button>
|
||
|
|
<span id="gpio-result" class="mono"></span>
|
||
|
|
</div>
|
||
|
|
<div class="card-row">
|
||
|
|
<label>PWM Freq:</label>
|
||
|
|
<input type="number" id="gpio-pwm-freq" class="input-text" value="1000" min="1" max="1000000">
|
||
|
|
<label>Duty:</label>
|
||
|
|
<input type="number" id="gpio-pwm-duty" class="input-text" value="50" min="0" max="100">
|
||
|
|
<button class="btn btn-small" onclick="gpioPwm()">Set PWM</button>
|
||
|
|
</div>
|
||
|
|
<div class="card-row">
|
||
|
|
<button class="btn btn-small" onclick="gpioAdc()">Read ADC</button>
|
||
|
|
<span id="gpio-adc-result" class="mono"></span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- ==================== SubGHz ==================== -->
|
||
|
|
<div class="page" id="page-subghz">
|
||
|
|
<div class="section">
|
||
|
|
<div class="section-title">Sub-GHz Radio</div>
|
||
|
|
<div class="card">
|
||
|
|
<div class="card-row">
|
||
|
|
<label>Frequency (Hz):</label>
|
||
|
|
<input type="number" id="subghz-freq" class="input-text" value="433920000">
|
||
|
|
<button class="btn btn-small" onclick="subghzSetFreq()">Set</button>
|
||
|
|
</div>
|
||
|
|
<div class="card-row">
|
||
|
|
<button class="btn" onclick="subghzRxStart()">Start RX</button>
|
||
|
|
<button class="btn btn-danger" onclick="subghzRxStop()">Stop RX</button>
|
||
|
|
<button class="btn btn-secondary" onclick="subghzGetRssi()">RSSI</button>
|
||
|
|
<span id="subghz-rssi" class="mono"></span>
|
||
|
|
</div>
|
||
|
|
<div class="card-row">
|
||
|
|
<label>TX Data (hex):</label>
|
||
|
|
<input type="text" id="subghz-tx-data" class="input-text" placeholder="deadbeef">
|
||
|
|
<button class="btn btn-small" onclick="subghzTx()">Transmit</button>
|
||
|
|
</div>
|
||
|
|
<div class="card-row">
|
||
|
|
<label>Replay slot:</label>
|
||
|
|
<input type="number" id="subghz-replay-slot" class="input-text" value="0" min="0" max="9">
|
||
|
|
<button class="btn btn-small" onclick="subghzReplay()">Replay</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="section-title" style="margin-top:16px">Captured Signals</div>
|
||
|
|
<div class="card">
|
||
|
|
<div class="log-output" id="subghz-log"></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- ==================== NFC/RFID ==================== -->
|
||
|
|
<div class="page" id="page-nfc">
|
||
|
|
<div class="section">
|
||
|
|
<div class="section-title">NFC (13.56 MHz)</div>
|
||
|
|
<div class="card">
|
||
|
|
<button class="btn" onclick="nfcPoll()">Poll Card</button>
|
||
|
|
<button class="btn" onclick="nfcReadFull()">Full Read</button>
|
||
|
|
<button class="btn btn-secondary" onclick="nfcRelayStart()">Start Relay</button>
|
||
|
|
<button class="btn btn-danger" onclick="nfcRelayStop()">Stop Relay</button>
|
||
|
|
<div class="log-output" id="nfc-log"></div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="section-title" style="margin-top:16px">RFID (125 kHz)</div>
|
||
|
|
<div class="card">
|
||
|
|
<button class="btn" onclick="rfidRead()">Read Tag</button>
|
||
|
|
<div class="card-row">
|
||
|
|
<label>Emulate UID (hex):</label>
|
||
|
|
<input type="text" id="rfid-emu-data" class="input-text" placeholder="0102030405">
|
||
|
|
<button class="btn btn-small" onclick="rfidEmulate()">Emulate</button>
|
||
|
|
</div>
|
||
|
|
<div class="log-output" id="rfid-log"></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- ==================== IR ==================== -->
|
||
|
|
<div class="page" id="page-ir">
|
||
|
|
<div class="section">
|
||
|
|
<div class="section-title">Infrared</div>
|
||
|
|
<div class="card">
|
||
|
|
<div class="card-row">
|
||
|
|
<label>Protocol:</label>
|
||
|
|
<select id="ir-proto" class="input-select">
|
||
|
|
<option value="0">NEC</option><option value="1">Samsung</option>
|
||
|
|
<option value="2">RC5</option><option value="3">RC6</option>
|
||
|
|
<option value="4">SIRC</option><option value="5">Kaseikyo</option>
|
||
|
|
</select>
|
||
|
|
<label>Addr:</label>
|
||
|
|
<input type="number" id="ir-addr" class="input-text" value="0">
|
||
|
|
<label>Cmd:</label>
|
||
|
|
<input type="number" id="ir-cmd" class="input-text" value="0">
|
||
|
|
<button class="btn btn-small" onclick="irTx()">Send</button>
|
||
|
|
</div>
|
||
|
|
<div class="card-row">
|
||
|
|
<button class="btn" onclick="irRxStart()">Start Learn</button>
|
||
|
|
<button class="btn btn-danger" onclick="irRxStop()">Stop</button>
|
||
|
|
<label>Replay:</label>
|
||
|
|
<input type="number" id="ir-replay-slot" class="input-text" value="0" min="0" max="9">
|
||
|
|
<button class="btn btn-small" onclick="irReplay()">Replay</button>
|
||
|
|
</div>
|
||
|
|
<div class="log-output" id="ir-log"></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- ==================== EVENTS ==================== -->
|
||
|
|
<div class="page" id="page-events">
|
||
|
|
<div class="section">
|
||
|
|
<div class="section-title">Live Events</div>
|
||
|
|
<div class="card">
|
||
|
|
<button class="btn btn-small" onclick="loadEvents()">Refresh</button>
|
||
|
|
<div class="log-output" id="events-log" style="max-height:60vh"></div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="section-title" style="margin-top:16px">System Log</div>
|
||
|
|
<div class="card">
|
||
|
|
<button class="btn btn-small" onclick="loadSysLog()">Load Log</button>
|
||
|
|
<div class="log-output" id="sys-log" style="max-height:40vh"></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- ==================== STEALTH ==================== -->
|
||
|
|
<div class="page" id="page-stealth">
|
||
|
|
<div class="section">
|
||
|
|
<div class="section-title">Namespace Isolation</div>
|
||
|
|
<div class="card">
|
||
|
|
<div class="card-row">
|
||
|
|
<div class="card-row-info">
|
||
|
|
<div class="card-row-label">Stealth Status</div>
|
||
|
|
<div class="card-row-desc">Bind mounts, port firewall, config hiding</div>
|
||
|
|
</div>
|
||
|
|
<span id="stealth-status-text" class="mono">-</span>
|
||
|
|
</div>
|
||
|
|
<div class="card-row">
|
||
|
|
<button class="btn" onclick="stealthApply()">Apply Stealth</button>
|
||
|
|
<button class="btn btn-danger" onclick="stealthTeardown()">Teardown</button>
|
||
|
|
<button class="btn btn-secondary" onclick="stealthStatus()">Status</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="section-title" style="margin-top:16px">Quick Controls</div>
|
||
|
|
<div class="card">
|
||
|
|
<div class="card-row">
|
||
|
|
<div class="card-row-info">
|
||
|
|
<div class="card-row-label">Hide Device + Port</div>
|
||
|
|
<div class="card-row-desc">Firewall WebUI to localhost, restrict config perms</div>
|
||
|
|
</div>
|
||
|
|
<button class="btn btn-small" onclick="stealthHideDev()">Hide</button>
|
||
|
|
<button class="btn btn-small" onclick="stealthShowDev()">Show</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="section-title" style="margin-top:16px">Stealth Map</div>
|
||
|
|
<div class="card">
|
||
|
|
<div class="card-row-desc" style="padding:8px">
|
||
|
|
Edit <code>/data/adb/flipperdroid/stealth_map.conf</code> to configure per-process bind mount isolation.
|
||
|
|
Stock files stay untouched. Only target processes see modifications.
|
||
|
|
</div>
|
||
|
|
<div class="card-row">
|
||
|
|
<label>Active bind mounts:</label>
|
||
|
|
<span id="stealth-mount-count" class="mono">-</span>
|
||
|
|
</div>
|
||
|
|
<div class="log-output" id="stealth-log"></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Toast -->
|
||
|
|
<div id="toast" class="toast"></div>
|
||
|
|
|
||
|
|
<!-- Tab bar -->
|
||
|
|
<div class="tab-bar">
|
||
|
|
<div class="tab-item active" data-tab="dashboard" onclick="switchTab('dashboard')">
|
||
|
|
<svg viewBox="0 0 24 24"><path d="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z"/></svg>
|
||
|
|
<span>Home</span>
|
||
|
|
</div>
|
||
|
|
<div class="tab-item" data-tab="gpio" onclick="switchTab('gpio')">
|
||
|
|
<svg viewBox="0 0 24 24"><path d="M7 2v11h3v9l7-12h-4l4-8z"/></svg>
|
||
|
|
<span>GPIO</span>
|
||
|
|
</div>
|
||
|
|
<div class="tab-item" data-tab="subghz" onclick="switchTab('subghz')">
|
||
|
|
<svg viewBox="0 0 24 24"><path d="M1 9l2 2c4.97-4.97 13.03-4.97 18 0l2-2C16.93 2.93 7.08 2.93 1 9zm8 8l3 3 3-3c-1.65-1.66-4.34-1.66-6 0zm-4-4l2 2c2.76-2.76 7.24-2.76 10 0l2-2C15.14 9.14 8.87 9.14 5 13z"/></svg>
|
||
|
|
<span>SubGHz</span>
|
||
|
|
</div>
|
||
|
|
<div class="tab-item" data-tab="nfc" onclick="switchTab('nfc')">
|
||
|
|
<svg viewBox="0 0 24 24"><path d="M20 2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 18H4V4h16v16zM6 6h2v2H6zm0 4h2v2H6zm0 4h2v2H6zm4-8h8v2h-8zm0 4h8v2h-8zm0 4h8v2h-8z"/></svg>
|
||
|
|
<span>NFC</span>
|
||
|
|
</div>
|
||
|
|
<div class="tab-item" data-tab="ir" onclick="switchTab('ir')">
|
||
|
|
<svg viewBox="0 0 24 24"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H3V5h18v14zM9 8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></svg>
|
||
|
|
<span>IR</span>
|
||
|
|
</div>
|
||
|
|
<div class="tab-item" data-tab="stealth" onclick="switchTab('stealth')">
|
||
|
|
<svg viewBox="0 0 24 24"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z"/></svg>
|
||
|
|
<span>Stealth</span>
|
||
|
|
</div>
|
||
|
|
<div class="tab-item" data-tab="events" onclick="switchTab('events')">
|
||
|
|
<svg viewBox="0 0 24 24"><path d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11z"/></svg>
|
||
|
|
<span>Log</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
</div>
|
||
|
|
<script src="/js/app.js"></script>
|
||
|
|
</body>
|
||
|
|
</html>
|