Files
yaris-obd/templates/settings.html
T
Mathieu MoranandCopilot cdb032b888 Add phone hotspot uplink
Prefer a configured phone hotspot for outbound synchronization, preserve secure write-only credentials, and recover through home WiFi or the local Pi hotspot.

Co-authored-by: Copilot <[email protected]>
2026-08-09 22:48:11 -04:00

171 lines
10 KiB
HTML

{% extends "base.html" %}
{% block title %}Settings - Yaris OBD{% endblock %}
{% block content %}
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mb-4">
<div>
<h3 class="text-dark mb-1">Settings</h3>
<p class="text-muted mb-0">Configuration stored locally on this Pi.</p>
</div>
<button class="btn btn-primary d-none d-md-inline-block settings-save" type="submit" form="settings-form" disabled>
<i class="fas fa-save me-1"></i>Save settings
</button>
</div>
<div id="settings-message" class="alert" role="status" hidden></div>
<form id="settings-form">
<div class="card shadow mb-4">
<div class="card-header py-3">
<p class="text-primary m-0 fw-bold">Uploads and local video</p>
</div>
<div class="card-body">
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="dashcam-upload-enabled">
<label class="form-check-label" for="dashcam-upload-enabled">Upload dashcam videos to the remote server</label>
</div>
<p class="text-muted small">Trip/GPS uploads remain enabled. Dashcam video only uploads over WiFi/Ethernet.</p>
<p id="upload-health" class="small mb-3">Checking remote upload status...</p>
<label class="form-label" for="retention-days">Delete uploaded local videos after</label>
<div class="input-group settings-number">
<input class="form-control" id="retention-days" type="number" min="0" max="3650" step="1" required>
<span class="input-group-text">days</span>
</div>
<div class="form-text">Use 0 to keep uploaded local copies until manually deleted.</div>
<div class="invalid-feedback" data-error-for="local_video_retention_days"></div>
</div>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<p class="text-primary m-0 fw-bold">Phone hotspot internet</p>
</div>
<div class="card-body">
<p id="uplink-status" class="mb-3">Checking network mode...</p>
<p id="last-phone-address" class="small mb-3" hidden>
Last phone-network address:
<a id="last-phone-address-link" href="#"></a>
<span class="text-muted">(DHCP may change it after reconnecting.)</span>
</p>
<div class="row g-3">
<div class="col-md-6">
<label class="form-label" for="phone-hotspot-ssid">Phone hotspot name</label>
<input class="form-control" id="phone-hotspot-ssid" maxlength="32" autocomplete="off">
</div>
<div class="col-md-6">
<label class="form-label" for="phone-hotspot-password">Phone hotspot password</label>
<input class="form-control" id="phone-hotspot-password" type="password" minlength="8" maxlength="63" autocomplete="new-password">
</div>
</div>
<div id="uplink-message" class="alert mt-3 mb-0" role="status" hidden></div>
<div class="d-flex flex-wrap gap-2 mt-3">
<button class="btn btn-primary" id="phone-hotspot-save" type="button">Save hotspot</button>
<button class="btn btn-outline-primary" id="phone-hotspot-connect" type="button" disabled>Wait for hotspot</button>
<button class="btn btn-outline-danger" id="phone-hotspot-remove" type="button" disabled>Remove hotspot</button>
</div>
<p class="form-text mb-0 mt-3">
Save while the phone is still connected to the Pi/home WiFi. Then select
<strong>Wait for hotspot</strong> and enable the phone hotspot within two minutes.
The password is write-only and is never returned here. This page may briefly close
while networks switch. Some phones do not resolve <strong>yaris.local</strong> for
tethered clients; use the last direct address shown above when needed. If the phone
hotspot never appears, the Pi restores home WiFi or its local hotspot.
</p>
</div>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<p class="text-primary m-0 fw-bold">Cellular trip-log fallback</p>
</div>
<div class="card-body">
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="cellular-enabled">
<label class="form-check-label" for="cellular-enabled">Enable SIM868 cellular fallback</label>
</div>
<label class="form-label" for="cellular-apn">Carrier APN</label>
<input class="form-control" id="cellular-apn" maxlength="100" autocomplete="off" placeholder="example.apn">
<div class="invalid-feedback" data-error-for="cellular_apn"></div>
<div class="form-text">Used only for small trip-log batches when WiFi/Ethernet is unavailable. Dashcam video never uses cellular.</div>
</div>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<p class="text-primary m-0 fw-bold">Optional ntfy notifications</p>
</div>
<div class="card-body">
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="ntfy-enabled">
<label class="form-check-label" for="ntfy-enabled">Send alerts through ntfy</label>
</div>
<label class="form-label" for="ntfy-url">ntfy topic URL</label>
<input class="form-control" id="ntfy-url" type="url" maxlength="2048" autocomplete="off" placeholder="https://ntfy.sh/private-topic">
<div class="invalid-feedback" data-error-for="ntfy_url"></div>
<div class="form-text" id="ntfy-url-state">Leave blank to keep the saved URL unchanged.</div>
<div class="form-check mt-2">
<input class="form-check-input" type="checkbox" id="clear-ntfy-url">
<label class="form-check-label" for="clear-ntfy-url">Remove saved ntfy URL</label>
</div>
<label class="form-label mt-3" for="ntfy-token">Access token</label>
<input class="form-control" id="ntfy-token" type="password" maxlength="512" autocomplete="new-password" placeholder="Optional">
<div class="invalid-feedback" data-error-for="ntfy_token"></div>
<div class="form-text" id="ntfy-token-state">Leave blank to keep the saved token unchanged.</div>
<div class="form-check mt-2">
<input class="form-check-input" type="checkbox" id="clear-ntfy-token">
<label class="form-check-label" for="clear-ntfy-token">Remove saved ntfy token</label>
</div>
</div>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<p class="text-primary m-0 fw-bold">Alert thresholds and repeat interval</p>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label" for="temperature-c">Pi temperature</label>
<div class="input-group"><input class="form-control" id="temperature-c" type="number" min="40" max="100" step="0.1" required><span class="input-group-text">°C</span></div>
<div class="invalid-feedback" data-error-for="temperature_c"></div>
</div>
<div class="col-md-6">
<label class="form-label" for="disk-percent">Pi/dashcam disk usage</label>
<div class="input-group"><input class="form-control" id="disk-percent" type="number" min="50" max="100" step="0.1" required><span class="input-group-text">%</span></div>
<div class="invalid-feedback" data-error-for="disk_percent"></div>
</div>
<div class="col-md-6">
<label class="form-label" for="tracking-backlog">Pending tracking rows</label>
<input class="form-control" id="tracking-backlog" type="number" min="1" max="1000000" step="1" required>
<div class="invalid-feedback" data-error-for="tracking_backlog"></div>
</div>
<div class="col-md-6">
<label class="form-label" for="video-backlog">Pending videos</label>
<input class="form-control" id="video-backlog" type="number" min="1" max="100000" step="1" required>
<div class="invalid-feedback" data-error-for="video_backlog"></div>
</div>
<div class="col-md-6">
<label class="form-label" for="gps-loss-seconds">GPS loss while moving</label>
<div class="input-group"><input class="form-control" id="gps-loss-seconds" type="number" min="10" max="3600" step="1" required><span class="input-group-text">seconds</span></div>
<div class="invalid-feedback" data-error-for="gps_loss_seconds"></div>
</div>
<div class="col-md-6">
<label class="form-label" for="repeat-seconds">Repeat active notifications</label>
<div class="input-group"><input class="form-control" id="repeat-seconds" type="number" min="60" max="604800" step="1" required><span class="input-group-text">seconds</span></div>
<div class="invalid-feedback" data-error-for="repeat_seconds"></div>
</div>
</div>
<p class="text-muted small mt-3 mb-0">Local Web UI alerts remain available even when ntfy is disabled.</p>
</div>
</div>
<button class="btn btn-primary w-100 d-md-none settings-save mb-4" type="submit" disabled>
<i class="fas fa-save me-1"></i>Save settings
</button>
</form>
{% endblock %}
{% block scripts %}
<script src="{{ url_for('static', filename='js/settings.js') }}"></script>
{% endblock %}