feat(ui): improve signal strength display with visual bars
Add colored signal bars (1-5) based on signal power level. Show signal quality description, RSSI in dBm, and quality index. Color coding: red (poor) -> orange -> yellow -> green -> blue (excellent). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
158
html/saraR4.html
158
html/saraR4.html
@@ -118,14 +118,18 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2">
|
||||
<div class="col-sm-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<p class="card-text">Signal strength </p>
|
||||
<button class="btn btn-primary" onclick="getData_saraR4('ttyAMA2', 'AT+CSQ', 1)">Get Data</button>
|
||||
<button class="btn btn-primary" onclick="getSignalInfo('ttyAMA2', 1)">Get Data</button>
|
||||
<div id="loading_ttyAMA2_AT_CSQ" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
|
||||
<div id="response_ttyAMA2_AT_CSQ"></div>
|
||||
</table>
|
||||
<div id="signal_info_alert"></div>
|
||||
<div class="collapse mt-2" id="signal_info_logs">
|
||||
<div class="card card-body bg-light">
|
||||
<small><code id="response_ttyAMA2_AT_CSQ"></code></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -787,6 +791,152 @@ function getNetworkInfo(port, timeout) {
|
||||
});
|
||||
}
|
||||
|
||||
function getSignalInfo(port, timeout) {
|
||||
console.log("Getting signal info from port " + port);
|
||||
|
||||
$("#loading_ttyAMA2_AT_CSQ").show();
|
||||
$("#signal_info_alert").empty();
|
||||
$("#response_ttyAMA2_AT_CSQ").empty();
|
||||
|
||||
$.ajax({
|
||||
url: 'launcher.php?type=sara&port=' + port + '&command=' + encodeURIComponent('AT+CSQ') + '&timeout=' + timeout,
|
||||
dataType: 'text',
|
||||
method: 'GET',
|
||||
success: function(response) {
|
||||
console.log("CSQ response:", response);
|
||||
$("#loading_ttyAMA2_AT_CSQ").hide();
|
||||
|
||||
// Store raw logs
|
||||
const formattedLogs = response.replace(/\n/g, "<br>");
|
||||
$("#response_ttyAMA2_AT_CSQ").html(formattedLogs);
|
||||
|
||||
// Parse response: +CSQ: <signal_power>,<qual>
|
||||
let alertHtml = '';
|
||||
const csqMatch = response.match(/\+CSQ:\s*(\d+),(\d+)/);
|
||||
|
||||
if (response.includes('OK') && csqMatch) {
|
||||
const signalPower = parseInt(csqMatch[1]);
|
||||
const qual = parseInt(csqMatch[2]);
|
||||
|
||||
// Determine signal quality and color
|
||||
let signalDesc, signalColor, signalIcon, alertClass;
|
||||
|
||||
if (signalPower === 99) {
|
||||
signalDesc = 'No signal';
|
||||
signalColor = '#333333';
|
||||
signalIcon = '⚫';
|
||||
alertClass = 'alert-dark';
|
||||
} else if (signalPower === 0) {
|
||||
signalDesc = 'Very poor';
|
||||
signalColor = '#dc3545';
|
||||
signalIcon = '🔴';
|
||||
alertClass = 'alert-danger';
|
||||
} else if (signalPower <= 9) {
|
||||
signalDesc = 'Poor';
|
||||
signalColor = '#fd7e14';
|
||||
signalIcon = '🟠';
|
||||
alertClass = 'alert-warning';
|
||||
} else if (signalPower <= 14) {
|
||||
signalDesc = 'Fair';
|
||||
signalColor = '#ffc107';
|
||||
signalIcon = '🟡';
|
||||
alertClass = 'alert-warning';
|
||||
} else if (signalPower <= 19) {
|
||||
signalDesc = 'Good';
|
||||
signalColor = '#20c997';
|
||||
signalIcon = '🟢';
|
||||
alertClass = 'alert-success';
|
||||
} else if (signalPower <= 25) {
|
||||
signalDesc = 'Very good';
|
||||
signalColor = '#198754';
|
||||
signalIcon = '🟢';
|
||||
alertClass = 'alert-success';
|
||||
} else if (signalPower <= 30) {
|
||||
signalDesc = 'Excellent';
|
||||
signalColor = '#0d6efd';
|
||||
signalIcon = '🔵';
|
||||
alertClass = 'alert-primary';
|
||||
} else {
|
||||
signalDesc = 'Maximum';
|
||||
signalColor = '#6f42c1';
|
||||
signalIcon = '🟣';
|
||||
alertClass = 'alert-primary';
|
||||
}
|
||||
|
||||
// Calculate approximate dBm (for RSSI: -113 + 2*signalPower)
|
||||
let rssiDbm = signalPower !== 99 ? (-113 + 2 * signalPower) + ' dBm' : 'N/A';
|
||||
|
||||
// Signal bars visualization (1-5 bars based on signal power)
|
||||
let bars = 0;
|
||||
if (signalPower !== 99) {
|
||||
if (signalPower >= 25) bars = 5;
|
||||
else if (signalPower >= 19) bars = 4;
|
||||
else if (signalPower >= 14) bars = 3;
|
||||
else if (signalPower >= 9) bars = 2;
|
||||
else if (signalPower >= 1) bars = 1;
|
||||
}
|
||||
|
||||
const barsHtml = `
|
||||
<span style="font-size: 1.2em; letter-spacing: 2px;">
|
||||
${[1,2,3,4,5].map(i =>
|
||||
`<span style="color: ${i <= bars ? signalColor : '#dee2e6'};">▮</span>`
|
||||
).join('')}
|
||||
</span>`;
|
||||
|
||||
alertHtml = `
|
||||
<div class="alert ${alertClass} py-2 mb-0 mt-2 d-flex justify-content-between align-items-center" role="alert">
|
||||
<div>
|
||||
<div class="d-flex align-items-center mb-1">
|
||||
${barsHtml}
|
||||
<span class="ms-2"><strong>${signalDesc}</strong></span>
|
||||
</div>
|
||||
<small>
|
||||
Signal: ${signalPower}/31 (${rssiDbm})<br>
|
||||
Quality: ${qual}/7
|
||||
</small>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-outline-secondary" type="button" data-bs-toggle="collapse" data-bs-target="#signal_info_logs" aria-expanded="false" aria-controls="signal_info_logs">
|
||||
<small>+</small>
|
||||
</button>
|
||||
</div>`;
|
||||
} else if (response.includes('ERROR') || response.trim() === '' || !response.includes('OK')) {
|
||||
alertHtml = `
|
||||
<div class="alert alert-danger py-2 mb-0 mt-2 d-flex justify-content-between align-items-center" role="alert">
|
||||
<div>
|
||||
<strong>Signal error</strong><br>
|
||||
<small>Unable to get signal info</small>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-outline-secondary" type="button" data-bs-toggle="collapse" data-bs-target="#signal_info_logs" aria-expanded="false" aria-controls="signal_info_logs">
|
||||
<small>+</small>
|
||||
</button>
|
||||
</div>`;
|
||||
} else {
|
||||
alertHtml = `
|
||||
<div class="alert alert-warning py-2 mb-0 mt-2 d-flex justify-content-between align-items-center" role="alert">
|
||||
<div>
|
||||
<strong>Unknown response</strong><br>
|
||||
<small>Check logs for details</small>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-outline-secondary" type="button" data-bs-toggle="collapse" data-bs-target="#signal_info_logs" aria-expanded="false" aria-controls="signal_info_logs">
|
||||
<small>+</small>
|
||||
</button>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
$("#signal_info_alert").html(alertHtml);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('AJAX request failed:', status, error);
|
||||
$("#loading_ttyAMA2_AT_CSQ").hide();
|
||||
$("#signal_info_alert").html(`
|
||||
<div class="alert alert-danger py-2 mb-0 mt-2" role="alert">
|
||||
<strong>Communication error</strong><br>
|
||||
<small>${error}</small>
|
||||
</div>`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getData_saraR4(port, command, timeout){
|
||||
console.log("Data from SaraR4");
|
||||
console.log("Port: " + port );
|
||||
|
||||
Reference in New Issue
Block a user