+ {% for unit in units %}
+
+
+
+
+ {% if unit.status == 'OK' %}
+
+ {% elif unit.status == 'Pending' %}
+
+ {% elif unit.status == 'Missing' %}
+
+ {% else %}
+
+ {% endif %}
+ {{ unit.id }}
+
+
+ {% if unit.status in ['N/A', 'Unknown'] %}Benched{% else %}{{ unit.status }}{% endif %}
+
+
+
+
+
+ {% if unit.device_type == 'modem' %}
+
+ Modem
+
+ {% else %}
+
+ Seismograph
+
+ {% endif %}
+
+
+
+ {% if unit.address %}
+
+ 📍 {{ unit.address }}
+
+ {% elif unit.coordinates %}
+
+ 📍 {{ unit.coordinates }}
+
+ {% endif %}
+
+
+ {% if unit.project_id %}
+
+ 🏗️ {{ unit.project_id }}
+
+ {% endif %}
+
+
+
+ 🕐 {{ unit.age }}
+
+
+
+
+ {% if unit.deployed %}
+
+ ⚡ Deployed
+
+ {% else %}
+
+ 📦 Benched
+
+ {% endif %}
+
+
+
+
+ Tap for details
+
+
+ {% endfor %}
+
+
+
+ Last updated: {{ timestamp }}
+
+
+
+
+
-
- Battery:
-
- {% if current_status and current_status.battery_level %}{{ current_status.battery_level }}%{% else %}--{% endif %}
-
-
-
- Power:
-
- {% if current_status and current_status.power_source %}{{ current_status.power_source }}{% else %}--{% endif %}
-
-
-
- Weighting:
-
- {% if unit.slm_frequency_weighting %}{{ unit.slm_frequency_weighting }}{% else %}--{% endif %} /
- {% if unit.slm_time_weighting %}{{ unit.slm_time_weighting }}{% else %}--{% endif %}
-
-
-
-
SD Remaining:
-
- {% if current_status and current_status.sd_remaining_mb %}{{ current_status.sd_remaining_mb }} MB{% else %}--{% endif %}
-
+
+
+
Device Status
+
+
+
+
+
+ {% if current_status and current_status.battery_level %}{{ current_status.battery_level }}%{% else %}--{% endif %}
+
+
+
+
+
+
+
+
+ {% if current_status and current_status.power_source %}{{ current_status.power_source }}{% else %}--{% endif %}
+
+
+
+
+
+
+
+ {% if current_status and current_status.sd_remaining_mb %}{{ current_status.sd_remaining_mb }} MB{% else %}--{% endif %}
+
+
+ {% if current_status and current_status.sd_free_ratio %}{{ current_status.sd_free_ratio }}% free{% else %}--{% endif %}
+
+
+
+
+
+
+
+ Just now
+
+
+
+ Auto-refresh: 30s
+
+
@@ -429,6 +470,94 @@ async function controlUnit(unitId, action) {
}
}
+
+// Auto-refresh status every 30 seconds
+let refreshInterval;
+const REFRESH_INTERVAL_MS = 30000; // 30 seconds
+const unit_id = '{{ unit.id }}';
+
+function updateDeviceStatus() {
+ fetch(`/api/slmm/${unit_id}/live`)
+ .then(response => response.json())
+ .then(result => {
+ if (result.status === 'ok' && result.data) {
+ const data = result.data;
+
+ // Update battery
+ if (document.getElementById('battery-level')) {
+ const batteryLevel = data.battery_level || '--';
+ document.getElementById('battery-level').textContent = batteryLevel === '--' ? '--' : `${batteryLevel}%`;
+
+ // Update battery bar
+ const batteryBar = document.getElementById('battery-bar');
+ if (batteryBar && batteryLevel !== '--') {
+ const level = parseInt(batteryLevel);
+ batteryBar.style.width = `${level}%`;
+
+ // Color based on level
+ if (level > 50) {
+ batteryBar.className = 'bg-green-500 h-2 rounded-full transition-all';
+ } else if (level > 20) {
+ batteryBar.className = 'bg-yellow-500 h-2 rounded-full transition-all';
+ } else {
+ batteryBar.className = 'bg-red-500 h-2 rounded-full transition-all';
+ }
+ }
+ }
+
+ // Update power source
+ if (document.getElementById('power-source')) {
+ document.getElementById('power-source').textContent = data.power_source || '--';
+ }
+
+ // Update SD card info
+ if (document.getElementById('sd-remaining')) {
+ const sdRemaining = data.sd_remaining_mb || '--';
+ document.getElementById('sd-remaining').textContent = sdRemaining === '--' ? '--' : `${sdRemaining} MB`;
+ }
+ if (document.getElementById('sd-ratio')) {
+ const sdRatio = data.sd_free_ratio || '--';
+ document.getElementById('sd-ratio').textContent = sdRatio === '--' ? '--' : `${sdRatio}% free`;
+ }
+
+ // Update last update timestamp
+ if (document.getElementById('last-update')) {
+ const now = new Date();
+ document.getElementById('last-update').textContent = now.toLocaleTimeString();
+ }
+ }
+ })
+ .catch(error => {
+ console.error('Failed to refresh device status:', error);
+ // Update last update with error indicator
+ if (document.getElementById('last-update')) {
+ document.getElementById('last-update').textContent = 'Update failed';
+ }
+ });
+}
+
+// Start auto-refresh
+function startAutoRefresh() {
+ // Initial update
+ updateDeviceStatus();
+
+ // Set up interval
+ refreshInterval = setInterval(updateDeviceStatus, REFRESH_INTERVAL_MS);
+ console.log('Auto-refresh started (30s interval)');
+}
+
+// Stop auto-refresh
+function stopAutoRefresh() {
+ if (refreshInterval) {
+ clearInterval(refreshInterval);
+ refreshInterval = null;
+ console.log('Auto-refresh stopped');
+ }
+}
+
+// Start auto-refresh when page loads
+document.addEventListener('DOMContentLoaded', startAutoRefresh);
+
// Cleanup on page unload
window.addEventListener('beforeunload', function() {
if (window.currentWebSocket) {
diff --git a/templates/partials/slm_live_view.html.backup b/templates/partials/slm_live_view.html.backup
new file mode 100644
index 0000000..d10264d
--- /dev/null
+++ b/templates/partials/slm_live_view.html.backup
@@ -0,0 +1,438 @@
+
+
+
+
+
+
{{ unit.id }}
+
+ {% if unit.slm_model %}{{ unit.slm_model }}{% endif %}
+ {% if unit.slm_serial_number %} • S/N: {{ unit.slm_serial_number }}{% endif %}
+
+ {% if modem %}
+
+ via Modem: {{ modem.id }}{% if modem_ip %} ({{ modem_ip }}){% endif %}
+
+ {% elif modem_ip %}
+
+ Direct: {{ modem_ip }}
+
+ {% else %}
+
+ ⚠️ No modem assigned or IP configured
+
+ {% endif %}
+
+
+
+
+ {% if is_measuring %}
+
+
+ Measuring
+
+ {% else %}
+
+ Stopped
+
+ {% endif %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Lp (Instant)
+
+ {% if current_status and current_status.lp %}{{ current_status.lp }}{% else %}--{% endif %}
+
+
dB
+
+
+
+
Leq (Average)
+
+ {% if current_status and current_status.leq %}{{ current_status.leq }}{% else %}--{% endif %}
+
+
dB
+
+
+
+
Lmax (Max)
+
+ {% if current_status and current_status.lmax %}{{ current_status.lmax }}{% else %}--{% endif %}
+
+
dB
+
+
+
+
Lmin (Min)
+
+ {% if current_status and current_status.lmin %}{{ current_status.lmin }}{% else %}--{% endif %}
+
+
dB
+
+
+
+
Lpeak (Peak)
+
+ {% if current_status and current_status.lpeak %}{{ current_status.lpeak }}{% else %}--{% endif %}
+
+
dB
+
+
+
+
+
+
+
+
+
+
+
+ Battery:
+
+ {% if current_status and current_status.battery_level %}{{ current_status.battery_level }}%{% else %}--{% endif %}
+
+
+
+ Power:
+
+ {% if current_status and current_status.power_source %}{{ current_status.power_source }}{% else %}--{% endif %}
+
+
+
+ Weighting:
+
+ {% if unit.slm_frequency_weighting %}{{ unit.slm_frequency_weighting }}{% else %}--{% endif %} /
+ {% if unit.slm_time_weighting %}{{ unit.slm_time_weighting }}{% else %}--{% endif %}
+
+
+
+ SD Remaining:
+
+ {% if current_status and current_status.sd_remaining_mb %}{{ current_status.sd_remaining_mb }} MB{% else %}--{% endif %}
+
+
+
+
+
+
+
diff --git a/templates/roster.html b/templates/roster.html
index dd5aae6..765e1e9 100644
--- a/templates/roster.html
+++ b/templates/roster.html
@@ -1,20 +1,20 @@
{% extends "base.html" %}
-{% block title %}Fleet Roster - Seismo Fleet Manager{% endblock %}
+{% block title %}Devices - Seismo Fleet Manager{% endblock %}
{% block content %}
-
Fleet Roster
-
Real-time status of all seismograph units
+
Devices
+
Manage all devices in your fleet
-
+
-
-
+
+
+
+
+
+
+
+
+ Type:
+
+
+
+
+
+
+
+
+ Status:
+
+
+
+
+
+
+
+
+
+ Health:
+
+
+
+
+
+
+
+
+
+ Showing 0 of 0 devices
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
Loading roster data...
+
Loading devices...
@@ -114,9 +112,9 @@