mirror of
https://github.com/colonelpanichacks/flock-you.git
synced 2026-06-11 14:43:30 -07:00
dashboard: env-configurable port, plus ?demo=1 preview mode
flockyou.py: bind host and listen port both read from env (FLOCKYOU_HOST / FLOCKYOU_PORT, defaulting to 0.0.0.0:5000). Was a hardcoded :5000 before, which collides with other Flask projects on the same dev box — now you can run side-by-side instances or bind to localhost only. index.html: ?demo=1 query param seeds the dashboard with eight synthetic detections covering every visual state (live wildcard-probe, addr2, addr1 with/without GPS, replay/FLASH with/without GPS, replay/ RAM × 2) and reveals the device command toolbar so the polished layout is browseable without flashing real hardware. Purely a front-end mock — the command buttons still hit the real /api/flock/* endpoints, so clicking them in demo mode produces the actual "device not connected" error toast (that error path is itself part of the UI worth seeing). Self-contained: a single initDemoMode() function gated on the query param, called once at the end of DOMContentLoaded. api/README.md: both features documented under Quick start so they're discoverable without reading the source.
This commit is contained in:
@@ -21,6 +21,14 @@ python flockyou.py
|
||||
|
||||
Open `http://localhost:5000`.
|
||||
|
||||
Port and bind address are env-configurable:
|
||||
|
||||
```bash
|
||||
FLOCKYOU_PORT=5101 FLOCKYOU_HOST=127.0.0.1 python flockyou.py
|
||||
```
|
||||
|
||||
Append `?demo=1` to the dashboard URL (`http://localhost:5000/?demo=1`) to load a front-end-only mock with the device shown as connected and a handful of sample detections covering every visual state — live, replay/FLASH (purple), replay/RAM (cyan), with and without GPS — so the polished layout and the command toolbar are previewable without flashing real hardware. The command buttons still hit the real `/api/flock/*` endpoints in demo mode, so clicking them produces the actual "device not connected" error toast.
|
||||
|
||||
1. Plug your Flock-You device in over USB.
|
||||
2. Pick its port from the **Sniffer** dropdown and click **Connect**.
|
||||
3. Five command buttons appear next to the connect controls — that's the host command protocol.
|
||||
|
||||
+6
-3
@@ -1763,12 +1763,15 @@ if __name__ == '__main__':
|
||||
heartbeat_thread = threading.Thread(target=send_heartbeat, daemon=True)
|
||||
heartbeat_thread.start()
|
||||
|
||||
host = os.environ.get('FLOCKYOU_HOST', '0.0.0.0')
|
||||
port = int(os.environ.get('FLOCKYOU_PORT', '5000'))
|
||||
|
||||
print("Starting Flock You API server...")
|
||||
print("Server will be available at: http://localhost:5000")
|
||||
print(f"Server will be available at: http://localhost:{port}")
|
||||
print("Press Ctrl+C to stop the server")
|
||||
|
||||
|
||||
try:
|
||||
socketio.run(app, debug=False, host='0.0.0.0', port=5000, allow_unsafe_werkzeug=True)
|
||||
socketio.run(app, debug=False, host=host, port=port, allow_unsafe_werkzeug=True)
|
||||
except KeyboardInterrupt:
|
||||
print("\nShutting down server...")
|
||||
# Clean up connections
|
||||
|
||||
@@ -1858,8 +1858,118 @@
|
||||
socket.connect();
|
||||
}
|
||||
}, 30000);
|
||||
|
||||
initDemoMode();
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// Demo mode — ?demo=1
|
||||
//
|
||||
// Seeds the dashboard with synthetic detections covering every
|
||||
// visual state (live, replay/FLASH, replay/RAM, with and without
|
||||
// GPS) and reveals the device command toolbar so the polished
|
||||
// layout is browseable without flashing real hardware.
|
||||
//
|
||||
// Purely a front-end mock. The command buttons still hit the
|
||||
// real /api/flock/* endpoints, so clicking them produces a
|
||||
// realistic "Flock device not connected" error toast — that
|
||||
// failure path is itself part of the UI worth previewing.
|
||||
// ============================================================
|
||||
function initDemoMode() {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
if (!params.has('demo')) return;
|
||||
|
||||
updateFlockStatus(true);
|
||||
setFlockExtraControls(true);
|
||||
|
||||
const sampleManufacturer = 'Espressif / Flock Safety';
|
||||
const now = new Date();
|
||||
const tIso = (deltaMs) => new Date(now.getTime() - deltaMs).toISOString();
|
||||
const tFmt = (deltaMs) => new Date(now.getTime() - deltaMs).toLocaleTimeString();
|
||||
|
||||
const samples = [
|
||||
{
|
||||
detection_method: 'wifi_wildcard_probe', protocol: 'wifi',
|
||||
mac_address: '70:c9:4e:81:b3:24', oui: '70:c9:4e',
|
||||
rssi: -52, last_rssi: -49, channel: 6, last_channel: 6,
|
||||
detection_count: 23, ssid: '',
|
||||
gps: { latitude: 37.3349, longitude: -122.0090, fix_quality: 1, satellites: 8, match_quality: 'temporal', time_diff: 1.2 },
|
||||
},
|
||||
{
|
||||
detection_method: 'wifi_oui_addr2', protocol: 'wifi',
|
||||
mac_address: '3c:91:80:14:f2:8a', oui: '3c:91:80',
|
||||
rssi: -67, last_rssi: -71, channel: 1, last_channel: 1,
|
||||
detection_count: 12, ssid: '',
|
||||
},
|
||||
{
|
||||
detection_method: 'wifi_oui_addr1', protocol: 'wifi',
|
||||
mac_address: 'd8:f3:bc:09:c1:5e', oui: 'd8:f3:bc',
|
||||
rssi: -78, last_rssi: -75, channel: 11, last_channel: 11,
|
||||
detection_count: 4, ssid: '',
|
||||
},
|
||||
{
|
||||
detection_method: 'wifi_wildcard_probe', protocol: 'wifi',
|
||||
mac_address: '82:6b:f2:7a:11:88', oui: '82:6b:f2',
|
||||
rssi: -61, last_rssi: -58, channel: 6, last_channel: 6,
|
||||
detection_count: 1, ssid: '',
|
||||
alias: 'DeFlockJoplin 12th cam',
|
||||
},
|
||||
{
|
||||
detection_method: 'wifi_oui_addr2', protocol: 'wifi',
|
||||
mac_address: 'b8:35:32:c0:de:01', oui: 'b8:35:32',
|
||||
rssi: -82, channel: 1, detection_count: 47, ssid: '',
|
||||
replay: true, replay_source: 'prev',
|
||||
timestamp_source: 'device_replay',
|
||||
device_first_ms: 12345, device_last_ms: 873400,
|
||||
},
|
||||
{
|
||||
detection_method: 'wifi_oui_addr1', protocol: 'wifi',
|
||||
mac_address: '14:b5:cd:33:9f:21', oui: '14:b5:cd',
|
||||
rssi: -74, channel: 11, detection_count: 8, ssid: '',
|
||||
replay: true, replay_source: 'prev',
|
||||
timestamp_source: 'device_replay',
|
||||
device_first_ms: 91100, device_last_ms: 902340,
|
||||
gps: { latitude: 37.4419, longitude: -122.1430, fix_quality: 1, satellites: 7, match_quality: 'temporal', time_diff: 3.8 },
|
||||
},
|
||||
{
|
||||
detection_method: 'wifi_oui_addr2', protocol: 'wifi',
|
||||
mac_address: '94:2a:6f:0e:44:b2', oui: '94:2a:6f',
|
||||
rssi: -69, channel: 6, detection_count: 3, ssid: '',
|
||||
replay: true, replay_source: 'live',
|
||||
timestamp_source: 'device_replay',
|
||||
device_first_ms: 1003000, device_last_ms: 1004900,
|
||||
},
|
||||
{
|
||||
detection_method: 'wifi_wildcard_probe', protocol: 'wifi',
|
||||
mac_address: 'f4:e2:c6:55:71:0d', oui: 'f4:e2:c6',
|
||||
rssi: -64, channel: 11, detection_count: 16, ssid: '',
|
||||
replay: true, replay_source: 'live',
|
||||
timestamp_source: 'device_replay',
|
||||
device_first_ms: 1010500, device_last_ms: 1080000,
|
||||
},
|
||||
];
|
||||
samples.forEach((s, i) => {
|
||||
s.id = 9000 + i;
|
||||
s.manufacturer = sampleManufacturer;
|
||||
s.alias = s.alias || '';
|
||||
if (!s.replay) {
|
||||
s.first_seen = tIso((samples.length - i) * 23_000);
|
||||
s.last_seen = tIso(i * 4_000);
|
||||
s.detection_time = tFmt(i * 4_000);
|
||||
s.timestamp = tIso(i * 4_000);
|
||||
s.timestamp_source = 'system';
|
||||
}
|
||||
detections.push(s);
|
||||
cumulativeDetections.push(s);
|
||||
});
|
||||
|
||||
updateStats();
|
||||
renderDetections();
|
||||
showFlockToast(
|
||||
'Demo mode active. Sample detections seeded; command buttons will toast errors (no real device).',
|
||||
'info', 7000);
|
||||
}
|
||||
|
||||
function setupEventListeners() {
|
||||
document.getElementById('filterSelect').addEventListener('change', function() {
|
||||
filterDetections(this.value);
|
||||
|
||||
Reference in New Issue
Block a user