CAT in line with rest of the code (using shared files now)

This commit is contained in:
Szymon Porwolik
2025-11-02 15:05:07 +01:00
parent 6f4ba3ed25
commit af13d4a316
5 changed files with 259 additions and 223 deletions

View File

@@ -35,13 +35,13 @@ class Bandmap extends CI_Controller {
$this->load->model('cat');
$this->load->model('bands');
$data['radios'] = $this->cat->radios();
$data['radio_last_updated'] = $this->cat->last_updated()->row();
$data['bands'] = $this->bands->get_user_bands_for_qso_entry();
$footerData = [];
$footerData['scripts'] = [
'assets/js/moment.min.js',
'assets/js/datetime-moment.js',
'assets/js/sections/bandmap_list.js'
];
// Get Date format

View File

@@ -10,6 +10,9 @@
var isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
var modKey = isMac ? 'Cmd' : 'Ctrl';
var lang_click_to_prepare_logging = "<?= __("Click to prepare logging."); ?> (" + modKey + "+Click <?= __("for new window"); ?>)";
// Enable compact radio status display for bandmap page
window.CAT_COMPACT_MODE = true;
</script>
<style>
@@ -24,14 +27,25 @@
text-decoration: none;
}
/* Make table rows clickable for prepare logging */
.spottable tbody tr,
.spottable tbody tr td,
.spottable tbody tr td *,
.spottable tbody tr span,
/* Make table rows clickable for prepare logging - use native alias cursor */
.spottable tbody tr {
cursor: alias !important;
}
.spottable tbody tr td {
cursor: alias !important;
}
/* Don't show alias cursor on loading/processing/empty rows */
.spottable tbody tr.dataTables_empty,
.spottable tbody tr.dataTables_empty td,
.spottable tbody td.dt-empty {
cursor: default !important;
}
/* Show standard pointer for clickable links (QRZ, POTA, SOTA, etc.) */
.spottable tbody tr a,
.spottable tbody tr td i,
.spottable tbody tr td .flag-emoji {
.spottable tbody tr td a {
cursor: pointer !important;
}
@@ -192,7 +206,7 @@
vertical-align: middle;
}
/* Fullscreen mode */
/* Fullscreen mode - CLEAN REBUILD */
.bandmap-logo-fullscreen {
display: none;
}
@@ -209,53 +223,86 @@
bottom: 0;
width: 100vw;
height: 100vh;
max-width: 100vw;
margin: 0;
padding: 0;
z-index: 9999;
overflow: hidden;
background: var(--bs-body-bg, #fff);
max-width: none !important;
padding: 0 !important;
}
.bandmap-fullscreen .card {
height: 100vh;
margin: 0;
border-radius: 0;
border: none;
display: flex;
flex-direction: column;
border: none;
}
.bandmap-fullscreen .card-header {
flex-shrink: 0;
flex: 0 0 auto;
}
.bandmap-fullscreen .card-body:first-of-type {
flex-shrink: 0;
flex-grow: 0;
padding: 0.5rem;
}
.bandmap-fullscreen .menu-bar {
flex-shrink: 0;
margin-bottom: 0;
}
.bandmap-fullscreen .card-body:last-child {
flex: 1 1 0;
.bandmap-fullscreen .card-body {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
overflow: auto;
gap: 0;
padding: 0.5rem;
overflow: auto;
}
/* Direct children of card-body in fullscreen */
.bandmap-fullscreen #radio_status {
flex: 0 0 auto;
margin: 0 !important;
padding: 0 !important;
min-height: 0 !important;
}
/* Only show margin when radio_status has content */
.bandmap-fullscreen #radio_status:not(:empty) {
margin: 0 0 0.5rem 0 !important;
}
.bandmap-fullscreen .menu-bar {
flex: 0 0 auto;
margin: 0 0 0.5rem 0 !important;
}
.bandmap-fullscreen .status-bar {
flex: 0 0 auto;
margin: 0 0 0.5rem 0 !important;
}
.bandmap-fullscreen .table-responsive {
flex: 1 1 auto;
min-height: 0;
overflow: auto;
margin: 0 !important;
}
/* Radio status compact mode styling (no card wrapper) */
#radio_status #radio_cat_state:not(.card) {
border: var(--bs-card-border-width, 1px) solid var(--bs-card-border-color, rgba(0,0,0,.125));
border-radius: 8px;
padding: 0.5rem;
margin: 0;
background-color: var(--bs-card-cap-bg, var(--bs-secondary-bg));
}
#radio_status #radio_cat_state:not(.card) > div {
margin: 0 !important;
padding: 0 !important;
}
/* In fullscreen, ensure proper spacing */
.bandmap-fullscreen #radio_status #radio_cat_state:not(.card) {
margin: 0 !important;
}
/* Z-index management */
.bandmap-fullscreen .dataTables_processing {
position: fixed;
top: 50%;
@@ -269,13 +316,11 @@
position: fixed;
}
/* Ensure tooltips appear above fullscreen mode */
body.fullscreen-active .tooltip,
.bandmap-fullscreen .tooltip {
z-index: 10003 !important;
}
/* Ensure modals appear above fullscreen mode */
body.fullscreen-active .modal,
body.fullscreen-active .modal-backdrop {
z-index: 10050 !important;
@@ -285,12 +330,12 @@
z-index: 10051 !important;
}
/* Hide page elements in fullscreen */
body.fullscreen-active #page-wrapper,
body.fullscreen-active nav,
body.fullscreen-active .navbar,
body.fullscreen-active header,
body.fullscreen-active #bandmapContainer > .d-flex.align-items-center.mb-3,
body.fullscreen-active #bandmapContainer > #radio_status,
body.fullscreen-active #bandmapContainer > .messages {
display: none !important;
}
@@ -319,7 +364,7 @@
margin-bottom: 5px;
}
/* Ensure CAT tracking and search box stay right-aligned when wrapping */
/* Ensure CAT Control and search box stay right-aligned when wrapping */
.menu-bar > div:last-child {
justify-content: flex-end;
}
@@ -453,26 +498,9 @@
}
</style>
<div class="container" id="bandmapContainer">
<div id="errormessage" style="display: none;"></div>
<!-- Radio Selector - Moved to top -->
<div class="d-flex align-items-center mb-3">
<label class="my-1 me-2" for="radio"><?= __("Radio"); ?></label>
<select class="form-select form-select-sm radios my-1 me-sm-2 w-auto" id="radio" name="radio">
<option value="0" selected="selected"><?= __("None"); ?></option>
<option value="ws"<?php if ($this->session->userdata('radio') == 'ws') { echo ' selected="selected"'; } ?>><?= __("WebSocket (Requires WLGate>1.1.10)"); ?></option>
<?php foreach ($radios->result() as $row) { ?>
<option value="<?php echo $row->id; ?>" <?php if ($this->session->userdata('radio') == $row->id) {
echo "selected=\"selected\"";
} ?>><?php echo $row->radio; ?></option>
<?php } ?>
</select>
</div>
<!-- Radio Status Panel (dynamically populated by JavaScript) -->
<div id="radio_status"></div>
<!-- Messages -->
<div class="messages my-1 mx-3"></div>
@@ -493,6 +521,9 @@
</div>
</div>
<div class="card-body pt-1">
<!-- Radio Status Panel (dynamically populated by JavaScript) -->
<div id="radio_status"></div>
<!-- Filters Section with darker background and rounded corners -->
<div class="menu-bar">
<!-- First Row: Band Filters, Mode Filters, and Continent Filters -->
@@ -701,11 +732,19 @@
</div>
</div>
<!-- CAT Tracking and Search wrapper - always right aligned -->
<!-- CAT Control and Search wrapper - always right aligned -->
<div class="d-flex gap-2 align-items-center ms-auto">
<!-- CAT Tracking Button -->
<!-- Radio Selector -->
<label class="my-0 me-2 flex-shrink-0 d-none d-md-inline" for="radio"><?= __("Radio"); ?></label>
<select class="form-select form-select-sm radios flex-shrink-0" id="radio" name="radio" style="width: auto; min-width: 150px;">
<option value="0" selected="selected"><?= __("None"); ?></option>
<option value="ws"<?php if ($this->session->userdata('radio') == 'ws') { echo ' selected="selected"'; } ?>><?= __("Live - ") . __("WebSocket (Requires WLGate>=1.1.10)"); ?></option>
<?php foreach ($radios->result() as $row) { ?>
<option value="<?php echo $row->id; ?>" <?php if($this->session->userdata('radio') == $row->id) { echo "selected=\"selected\""; } ?>><?= __("Polling - ") . $row->radio; ?><?php if ($radio_last_updated->id == $row->id) { echo "(".__("last updated").")"; } else { echo ''; } ?></option>
<?php } ?>
</select> <!-- CAT Control Button -->
<button class="btn btn-sm btn-primary flex-shrink-0" type="button" id="toggleCatTracking" title="<?= __("When selected the filters will be set basing on your current radio status"); ?>">
<i class="fas fa-radio"></i> <span class="d-none d-sm-inline">CAT tracking</span>
<i class="fas fa-radio"></i> <span class="d-none d-sm-inline">CAT Control</span>
</button>
<!-- Search Input -->
@@ -760,3 +799,4 @@
</div>
</div>

View File

@@ -1463,6 +1463,12 @@ mymap.on('mousemove', onQsoMapMove);
<?php } ?>
<!--- Bandmap CAT Integration --->
<?php if ($this->uri->segment(1) == "bandmap" && $this->uri->segment(2) == "list") { ?>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/cat.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/sections/bandmap_list.js"></script>
<?php } ?>
<?php if ($this->uri->segment(1) == "logbook" && $this->uri->segment(2) == "view") { ?>
<script>
@@ -3342,6 +3348,6 @@ if (isset($scripts) && is_array($scripts)){
}
?>
<!-- Toast Notification - used by showToast() from common.js -->
<div id="toast-container" class="position-fixed top-0 end-0 p-3" style="z-index: 1100;"></div>
<div id="toast-container" class="position-fixed top-0 end-0 p-3" style="z-index: 10100;"></div>
</body>
</html>

View File

@@ -70,6 +70,10 @@ $(document).ready(function() {
LOCK_TIMEOUT_MS: 10000
};
// Global setting for radio status display mode (can be set by pages like bandmap)
// Default: false (use card wrapper), can be set to true for compact mode
window.CAT_COMPACT_MODE = window.CAT_COMPACT_MODE || false;
function initializeWebSocketConnection() {
try {
// Note: Browser will log WebSocket connection errors to console if server is unreachable
@@ -340,17 +344,16 @@ $(document).ready(function() {
}
/**
* Display radio status panel with unified styling
* Handles success (active connection), error (connection lost), timeout (stale data), and not_logged_in states
* Display radio status panel with current CAT information
* Creates or updates a Bootstrap card panel showing radio connection status and frequency data
* Includes visual feedback with color-coded icon and blink animation on updates
* Respects global CAT_COMPACT_MODE setting for rendering style
* @param {string} state - Display state: 'success', 'error', 'timeout', or 'not_logged_in'
* @param {object|string} data - Radio data object (success) or radio name string (error/timeout/not_logged_in)
*/
function displayRadioStatus(state, data) {
var iconClass, content;
var baseStyle = '<div style="display: flex; align-items: center; font-size: calc(1rem - 2px);">';
if (state === 'success') {
var baseStyle = '<div style="display: flex; align-items: center; font-size: calc(1rem - 2px);">'; if (state === 'success') {
// Success state - display radio info
iconClass = 'text-success'; // Bootstrap green for success
@@ -440,41 +443,64 @@ $(document).ready(function() {
var icon = '<i id="radio-status-icon" class="fas fa-radio ' + iconClass + '" style="margin-right: 10px; font-size: 1.2em;"></i>';
var html = baseStyle + icon + content + '</div>';
// Update DOM
if (!$('#radio_cat_state').length) {
// Create panel if it doesn't exist
$('#radio_status').prepend('<div id="radio_cat_state" class="card"><div class="card-body">' + html + '</div></div>');
} else {
// Dispose of existing tooltips before updating content
$('#radio_cat_state [data-bs-toggle="tooltip"]').each(function() {
var tooltipInstance = bootstrap.Tooltip.getInstance(this);
if (tooltipInstance) {
tooltipInstance.dispose();
}
});
// Update existing panel content
$('#radio_cat_state .card-body').html(html);
} // Initialize Bootstrap tooltips for any new tooltip elements in the radio panel
$('#radio_cat_state [data-bs-toggle="tooltip"]').each(function() {
new bootstrap.Tooltip(this);
});
// Update DOM based on global CAT_COMPACT_MODE setting
if (window.CAT_COMPACT_MODE) {
// Compact mode: inject directly without card wrapper
if (!$('#radio_cat_state').length) {
$('#radio_status').prepend('<div id="radio_cat_state">' + html + '</div>');
} else {
// Dispose of existing tooltips before updating content
$('#radio_cat_state [data-bs-toggle="tooltip"]').each(function() {
var tooltipInstance = bootstrap.Tooltip.getInstance(this);
if (tooltipInstance) {
tooltipInstance.dispose();
}
});
$('#radio_cat_state').html(html);
}
} else {
// Standard mode: create card wrapper (default for backward compatibility)
if (!$('#radio_cat_state').length) {
// Create panel if it doesn't exist
$('#radio_status').prepend('<div id="radio_cat_state" class="card"><div class="card-body">' + html + '</div></div>');
} else {
// Dispose of existing tooltips before updating content
$('#radio_cat_state [data-bs-toggle="tooltip"]').each(function() {
var tooltipInstance = bootstrap.Tooltip.getInstance(this);
if (tooltipInstance) {
tooltipInstance.dispose();
}
});
// Update existing panel content
$('#radio_cat_state .card-body').html(html);
}
}
// Trigger blink animation on successful updates
if (state === 'success') {
$('#radio-status-icon').addClass('radio-icon-blink');
setTimeout(function() {
$('#radio-status-icon').removeClass('radio-icon-blink');
}, 400);
}
}
// Initialize Bootstrap tooltips for any new tooltip elements in the radio panel
$('#radio_cat_state [data-bs-toggle="tooltip"]').each(function() {
new bootstrap.Tooltip(this);
});
// Trigger blink animation on successful updates
if (state === 'success') {
$('#radio-status-icon').addClass('radio-icon-blink');
setTimeout(function() {
$('#radio-status-icon').removeClass('radio-icon-blink');
}, 400);
}
}
/**
* Process CAT data and update UI elements
* Performs timeout check, updates form fields, and displays radio status
* Handles both WebSocket and polling data sources
* Exposed globally for extension by other components (e.g., bandmap)
* @param {object} data - CAT data object from radio (includes frequency, mode, power, etc.)
*/
function updateCATui(data) {
window.updateCATui = function updateCATui(data) {
// Store last CAT data globally for other components (e.g., bandmap)
window.lastCATData = data;
// Check if data is too old FIRST - before any UI updates
// cat_timeout_minutes is set in footer.php from PHP config
var minutes = cat_timeout_minutes;

View File

@@ -973,6 +973,11 @@ $(function() {
table.page.len(50);
if (dxspots.length > 0) {
// Filter out spots with no frequency or frequency = 0
dxspots = dxspots.filter(spot => {
return spot.frequency && parseFloat(spot.frequency) > 0;
});
dxspots.sort(SortByQrg); // Sort by frequency
cachedSpotData = dxspots;
} else {
@@ -1285,7 +1290,6 @@ $(function() {
let bc2qso = new BroadcastChannel('qso_wish');
var CatCallbackURL = "http://127.0.0.1:54321";
var isCatTrackingEnabled = false; // Track CAT tracking button state
let wait4pong = 2000;
let check_intv = 100;
@@ -1304,6 +1308,8 @@ $(function() {
if (pong_rcvd || ((Date.now() - qso_window_last_seen) < wait4pong)) {
clearInterval(check_pong);
bc2qso.postMessage({ frequency: qrg, call: call });
// Show toast notification when callsign is sent to existing QSO window
showToast('QSO Prepared', `Callsign ${call} sent to logging form`, 'bg-success text-white', 3000);
} else {
clearInterval(check_pong);
let cl={};
@@ -1319,6 +1325,8 @@ $(function() {
}, 3000);
} else {
newWindow.focus();
// Show toast notification when opening new QSO window
showToast('QSO Prepared', `Callsign ${call} sent to logging form`, 'bg-success text-white', 3000);
}
bc2qso.onmessage = function(ev) {
@@ -1364,152 +1372,83 @@ $(function() {
}
});
let websocket = null;
let reconnectAttempts = 0;
let websocketEnabled = false;
let CATInterval=null;
// ========================================
// CAT CONTROL INTEGRATION
// ========================================
// Note: WebSocket and AJAX polling infrastructure is handled by cat.js
// We extend cat.js functionality for bandmap-specific band filtering
function initializeWebSocketConnection() {
try {
websocket = new WebSocket('ws://localhost:54322');
websocket.onopen = function(event) {
reconnectAttempts = 0;
websocketEnabled = true;
};
websocket.onmessage = function(event) {
try {
const data = JSON.parse(event.data);
handleWebSocketData(data);
} catch (error) {
}
};
websocket.onerror = function(error) {
websocketEnabled=false;
};
websocket.onclose = function(event) {
websocketEnabled = false;
var isCatTrackingEnabled = false; // Track CAT Control button state
if (reconnectAttempts < 5) {
setTimeout(() => {
reconnectAttempts++;
initializeWebSocketConnection();
}, 2000 * reconnectAttempts);
} else {
$(".radio_cat_state" ).remove();
$('#radio_status').html('<div class="alert alert-danger radio_timeout_error" role="alert"><i class="fas fa-broadcast-tower"></i> Radio connection timed-out: ' + $('select.radios option:selected').text() + ' Websocket connection lost, chose another radio.</div>');
websocketEnabled = false;
}
};
} catch (error) {
websocketEnabled=false;
}
}
// Save reference to cat.js's updateCATui if it exists
var catJsUpdateCATui = window.updateCATui;
function handleWebSocketData(data) {
if (data.type === 'welcome') {
return;
}
if (data.type === 'radio_status' && data.radio && ($(".radios option:selected").val() == 'ws')) {
data.updated_minutes_ago = Math.floor((Date.now() - data.timestamp) / 60000);
data.cat_url = 'http://127.0.0.1:54321';
updateCATui(data);
}
}
// Override updateCATui to add bandmap-specific behavior
window.updateCATui = function(data) {
console.log('Bandmap: updateCATui called with data:', data);
$( "#radio" ).change(function() {
if (CATInterval) {
clearInterval(CATInterval);
CATInterval=null;
}
if (websocket) {
websocket.close();
websocketEnabled = false;
}
if ($("#radio option:selected").val() == '0') {
$('#radio_status').html('');
} else if ($("#radio option:selected").val() == 'ws') {
initializeWebSocketConnection();
} else {
// Update frequency every three second
CATInterval=setInterval(updateFromCAT, 3000);
}
});
function updateCATui(data) {
const band = frequencyToBand(data.frequency);
CatCallbackURL=data.cat_url;
CatCallbackURL = data.cat_url || 'http://127.0.0.1:54321';
console.log('CAT Update - Frequency:', data.frequency, 'Band:', band, 'Tracking enabled:', isCatTrackingEnabled, 'Current band filter:', $("#band").val());
console.log('Bandmap CAT Update - Frequency:', data.frequency, 'Band:', band, 'Control enabled:', isCatTrackingEnabled);
// Only update band filter if CAT tracking is enabled
// Bandmap-specific: Update band filter if CAT Control is enabled
if (isCatTrackingEnabled) {
const currentBands = $("#band").val() || [];
// Check if current selection is not just this band
if (currentBands.length !== 1 || currentBands[0] !== band) {
console.log('Updating band filter to:', band);
$("#band").val([band]);
updateSelectCheckboxes('band');
syncQuickFilterButtons();
applyFilters(false);
}
}
const minutes = Math.floor(cat_timeout_interval / 60);
if(data.updated_minutes_ago > minutes) {
if ($('#radio_status').length) {
$('#radio_status').html('<div class="alert alert-danger mb-2" role="alert"><i class="fas fa-broadcast-tower"></i> Radio connection timed-out: ' + $('select.radios option:selected').text() + ' data is ' + data.updated_minutes_ago + ' minutes old.</div>');
}
} else {
$(".radio_timeout_error" ).remove();
var text = '<i class="fas fa-broadcast-tower"></i><span style="margin-left:10px;"></span><b>TX:</b> '+(Math.round(parseInt(data.frequency)/100)/10000).toFixed(4)+' MHz';
highlight_current_qrg((parseInt(data.frequency))/1000);
if(data.mode != null) {
text = text+'<span style="margin-left:10px"></span>'+data.mode;
}
if(data.power != null && data.power != 0) {
text = text+'<span style="margin-left:10px"></span>'+data.power+' W';
}
if ($('#radio_status').length) {
$('#radio_status').html('<div class="alert alert-success mb-2" role="alert">'+text+'</div>');
}
}
}
var updateFromCAT = function() {
if($('select.radios option:selected').val() != '0') {
var radioID = $('select.radios option:selected').val();
$.getJSON( base_url+"index.php/radio/json/" + radioID, function( data ) {
if (data.error) {
if (data.error == 'not_logged_in') {
$(".radio_cat_state" ).remove();
if($('.radio_login_error').length == 0) {
$('.messages').prepend('<div class="alert alert-danger radio_login_error" role="alert"><i class="fas fa-broadcast-tower"></i> You\'re not logged it. Please <a href="'+base_url+'">login</a></div>');
}
if (band && band !== '') {
// Valid band found - set filter to this specific band
// Check if current selection is not just this band
if (currentBands.length !== 1 || currentBands[0] !== band) {
console.log('Updating band filter to:', band);
$("#band").val([band]);
updateSelectCheckboxes('band');
syncQuickFilterButtons();
applyFilters(false);
// Show toast notification when band filter is changed by CAT
if (typeof showToast === 'function') {
showToast('CAT Control', `Frequency filter changed to ${band} by transceiver`, 'bg-info text-white', 3000);
}
// Put future Errorhandling here
} else {
if($('.radio_login_error').length != 0) {
$(".radio_login_error" ).remove();
}
updateCATui(data);
}
});
} else {
// No band match - clear band filter to show all bands
if (currentBands.length > 0 || !currentBands.includes('All')) {
console.log('Frequency outside known bands - clearing band filter to show all');
$("#band").val(['All']);
updateSelectCheckboxes('band');
syncQuickFilterButtons();
applyFilters(false);
// Show toast notification
if (typeof showToast === 'function') {
showToast('CAT Control', 'Frequency outside known bands - showing all bands', 'bg-warning text-dark', 3000);
}
}
}
}
// Bandmap-specific: Highlight current QRG in the spot list
if (data.frequency) {
highlight_current_qrg((parseInt(data.frequency))/1000);
}
// Call cat.js's original updateCATui for standard CAT UI updates
if (typeof catJsUpdateCATui === 'function') {
console.log('Bandmap: Calling cat.js updateCATui');
catJsUpdateCATui(data);
} else {
console.warn('Bandmap: cat.js updateCATui not available');
}
};
$.fn.dataTable.moment(custom_date_format + ' HH:mm');
console.log('Bandmap: CAT integration complete, updateCATui override installed');
$('#radio').change();
$.fn.dataTable.moment(custom_date_format + ' HH:mm');
let isFullscreen = false;
$('#fullscreenToggle').on('click', function() {
const container = $('#bandmapContainer');
const icon = $('#fullscreenIcon');
const radioSelector = container.find('.d-flex.align-items-center.mb-3').first();
if (!isFullscreen) {
container.addClass('bandmap-fullscreen');
@@ -1517,10 +1456,6 @@ $(function() {
icon.removeClass('fa-expand').addClass('fa-compress');
$(this).attr('title', 'Exit Fullscreen');
radioSelector.hide();
$('#radio_status').hide();
$('.messages').hide();
isFullscreen = true;
// Request browser fullscreen
@@ -1546,10 +1481,6 @@ $(function() {
icon.removeClass('fa-compress').addClass('fa-expand');
$(this).attr('title', 'Toggle Fullscreen');
radioSelector.show();
$('#radio_status').show();
$('.messages').show();
isFullscreen = false;
// Exit browser fullscreen
@@ -2080,22 +2011,55 @@ $(function() {
applyFilters(false);
});
// Toggle CAT tracking
// Toggle CAT Control
$('#toggleCatTracking').on('click', function() {
let btn = $(this);
if (btn.hasClass('btn-warning')) {
// Disable CAT tracking
// Disable CAT Control
btn.removeClass('btn-warning').addClass('btn-primary');
btn.find('i').removeClass('fa-check-circle').addClass('fa-radio');
isCatTrackingEnabled = false;
console.log('CAT Tracking disabled');
console.log('CAT Control disabled');
} else {
// Enable CAT tracking
// Enable CAT Control
btn.removeClass('btn-primary').addClass('btn-warning');
btn.find('i').removeClass('fa-radio').addClass('fa-check-circle');
isCatTrackingEnabled = true;
console.log('CAT Tracking enabled');
console.log('CAT Control enabled');
// Immediately apply current radio frequency if available
if (window.lastCATData && window.lastCATData.frequency) {
console.log('Applying current radio frequency:', window.lastCATData.frequency);
const band = frequencyToBand(window.lastCATData.frequency);
if (band && band !== '') {
// Valid band found - set filter to this specific band
console.log('Setting band filter to:', band);
$("#band").val([band]);
updateSelectCheckboxes('band');
syncQuickFilterButtons();
applyFilters(false);
if (typeof showToast === 'function') {
showToast('CAT Control', `Frequency filter set to ${band} by transceiver`, 'bg-info text-white', 3000);
}
} else {
// No band match - clear band filter to show all bands
console.log('Frequency outside known bands - showing all');
$("#band").val(['All']);
updateSelectCheckboxes('band');
syncQuickFilterButtons();
applyFilters(false);
if (typeof showToast === 'function') {
showToast('CAT Control', 'Frequency outside known bands - showing all bands', 'bg-warning text-dark', 3000);
}
}
} else {
console.log('No radio data available yet - waiting for next CAT update');
if (typeof showToast === 'function') {
showToast('CAT Control', 'Waiting for radio data...', 'bg-info text-white', 2000);
}
}
}
});