espilon-source/tools/C3PO/templates/mlat.html
Eun0us 8b6c1cd53d ε - ChaCha20-Poly1305 AEAD + HKDF crypto upgrade + C3PO rewrite + docs
Crypto:
- Replace broken ChaCha20 (static nonce) with ChaCha20-Poly1305 AEAD
- HKDF-SHA256 key derivation from per-device factory NVS master keys
- Random 12-byte nonce per message (ESP32 hardware RNG)
- crypto_init/encrypt/decrypt API with mbedtls legacy (ESP-IDF v5.3.2)
- Custom partition table with factory NVS (fctry at 0x10000)

Firmware:
- crypto.c full rewrite, messages.c device_id prefix + AEAD encrypt
- crypto_init() at boot with esp_restart() on failure
- Fix command_t initializations across all modules (sub/help fields)
- Clean CMakeLists dependencies for ESP-IDF v5.3.2

C3PO (C2):
- Rename tools/c2 + tools/c3po -> tools/C3PO
- Per-device CryptoContext with HKDF key derivation
- KeyStore (keys.json) for master key management
- Transport parses device_id:base64(...) wire format

Tools:
- New tools/provisioning/provision.py for factory NVS key generation
- Updated flasher with mbedtls config for v5.3.2

Docs:
- Update all READMEs for new crypto, C3PO paths, provisioning
- Update roadmap, architecture diagrams, security sections
- Update CONTRIBUTING.md project structure
2026-02-10 21:28:45 +01:00

175 lines
7.4 KiB
HTML

{% extends "base.html" %}
{% block title %}MLAT - ESPILON{% endblock %}
{% block head %}
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
{% endblock %}
{% block content %}
<div class="page-header">
<div class="page-title">MLAT <span>Multilateration Positioning</span></div>
<div class="view-toggle">
<button class="view-btn active" data-view="map" onclick="switchView('map')">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="10" r="3"/><path d="M12 21.7C17.3 17 20 13 20 10a8 8 0 1 0-16 0c0 3 2.7 7 8 11.7z"/>
</svg>
Map
</button>
<button class="view-btn" data-view="plan" onclick="switchView('plan')">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18M9 21V9"/>
</svg>
Plan
</button>
</div>
</div>
<div class="mlat-container">
<!-- Map/Plan View -->
<div class="mlat-view-wrapper">
<!-- Leaflet Map View -->
<div id="map-view" class="mlat-view active">
<div id="leaflet-map"></div>
</div>
<!-- Plan View (Canvas + Image) -->
<div id="plan-view" class="mlat-view">
<div class="plan-controls">
<input type="file" id="plan-upload" accept="image/*" style="display:none" onchange="uploadPlanImage(this)">
<button class="btn btn-sm" onclick="document.getElementById('plan-upload').click()">
Upload Plan
</button>
<button class="btn btn-sm" onclick="clearPlan()">
Clear
</button>
<div class="control-divider"></div>
<button class="btn btn-sm toggle-btn active" id="grid-toggle" onclick="toggleGrid()">
Grid
</button>
<button class="btn btn-sm toggle-btn active" id="labels-toggle" onclick="toggleLabels()">
Labels
</button>
<div class="control-divider"></div>
<span class="control-label">Zoom:</span>
<button class="btn btn-sm" onclick="zoomPlan(-1)" title="Zoom Out">-</button>
<span class="zoom-level" id="zoom-level">100%</span>
<button class="btn btn-sm" onclick="zoomPlan(1)" title="Zoom In">+</button>
<button class="btn btn-sm" onclick="resetZoom()" title="Reset View">Reset</button>
<div class="control-divider"></div>
<span class="control-label">Size:</span>
<button class="btn btn-sm" onclick="adjustPlanSize(-10)" title="Shrink Plan">-10m</button>
<span class="size-display" id="size-display">50x30m</span>
<button class="btn btn-sm" onclick="adjustPlanSize(10)" title="Enlarge Plan">+10m</button>
</div>
<div class="plan-canvas-wrapper">
<canvas id="plan-canvas"></canvas>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="mlat-sidebar">
<!-- Target Position -->
<div class="mlat-panel">
<h3>Target Position</h3>
<div class="mlat-stat" id="target-coord1-row">
<span class="label" id="target-coord1-label">Latitude</span>
<span class="value" id="target-coord1">-</span>
</div>
<div class="mlat-stat" id="target-coord2-row">
<span class="label" id="target-coord2-label">Longitude</span>
<span class="value" id="target-coord2">-</span>
</div>
<div class="mlat-stat">
<span class="label">Confidence</span>
<span class="value" id="target-confidence">-</span>
</div>
<div class="mlat-stat">
<span class="label">Last Update</span>
<span class="value" id="target-age">-</span>
</div>
<div class="mlat-stat">
<span class="label">Mode</span>
<span class="value" id="coord-mode">GPS</span>
</div>
</div>
<!-- Active Scanners -->
<div class="mlat-panel">
<h3>Scanners (<span id="scanner-count">0</span>)</h3>
<div class="scanner-list" id="scanner-list">
<div class="empty">No scanners active</div>
</div>
</div>
<!-- Map Settings (GPS mode) -->
<div class="mlat-panel" id="map-settings">
<h3>Map Settings (GPS)</h3>
<div class="config-row">
<label>Center Lat</label>
<input type="number" id="map-center-lat" value="48.8566" step="0.0001">
</div>
<div class="config-row">
<label>Center Lon</label>
<input type="number" id="map-center-lon" value="2.3522" step="0.0001">
</div>
<div class="config-row">
<label>Zoom</label>
<input type="number" id="map-zoom" value="18" min="1" max="20">
</div>
<button class="btn btn-primary btn-sm" onclick="centerMap()">Center Map</button>
<button class="btn btn-sm" onclick="fitMapToBounds()">Fit to Scanners</button>
</div>
<!-- Plan Settings (Local mode) -->
<div class="mlat-panel" id="plan-settings" style="display:none">
<h3>Plan Settings (Local)</h3>
<div class="config-row">
<label>Width (m)</label>
<input type="number" id="plan-width" value="50" min="1" step="1">
</div>
<div class="config-row">
<label>Height (m)</label>
<input type="number" id="plan-height" value="30" min="1" step="1">
</div>
<div class="config-row">
<label>Origin X (m)</label>
<input type="number" id="plan-origin-x" value="0" step="0.1">
</div>
<div class="config-row">
<label>Origin Y (m)</label>
<input type="number" id="plan-origin-y" value="0" step="0.1">
</div>
<button class="btn btn-primary btn-sm" onclick="applyPlanSettings()">Apply</button>
</div>
<!-- MLAT Configuration -->
<div class="mlat-panel">
<h3>MLAT Config</h3>
<div class="config-row">
<label>RSSI @ 1m</label>
<input type="number" id="config-rssi" value="-40" step="1">
</div>
<div class="config-row">
<label>Path Loss (n)</label>
<input type="number" id="config-n" value="2.5" step="0.1">
</div>
<div class="config-row">
<label>Smoothing</label>
<input type="number" id="config-smooth" value="5" min="1" max="20">
</div>
<div class="btn-group">
<button class="btn btn-primary btn-sm" onclick="saveConfig()">Save</button>
<button class="btn btn-secondary btn-sm" onclick="clearData()">Clear All</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script src="{{ url_for('static', filename='js/mlat.js') }}"></script>
{% endblock %}