Files
vna_system/vna_system/web_ui/static/js/modules/acquisition.js
2025-09-25 17:38:53 +03:00

255 lines
8.6 KiB
JavaScript

/**
* Acquisition Control Module
* Handles VNA data acquisition control via REST API
*/
export class AcquisitionManager {
constructor(notifications) {
this.notifications = notifications;
this.isInitialized = false;
this.currentStatus = {
running: false,
paused: false,
continuous_mode: true,
sweep_count: 0
};
// Bind methods
this.handleStartClick = this.handleStartClick.bind(this);
this.handleStopClick = this.handleStopClick.bind(this);
this.handleSingleSweepClick = this.handleSingleSweepClick.bind(this);
this.updateStatus = this.updateStatus.bind(this);
}
initialize() {
if (this.isInitialized) return;
// Get DOM elements
this.elements = {
startBtn: document.getElementById('startBtn'),
stopBtn: document.getElementById('stopBtn'),
singleSweepBtn: document.getElementById('singleSweepBtn'),
statusText: document.getElementById('acquisitionStatusText'),
statusDot: document.querySelector('.status-indicator__dot'),
modeText: document.getElementById('acquisitionModeText')
};
// Add event listeners
this.elements.startBtn?.addEventListener('click', this.handleStartClick);
this.elements.stopBtn?.addEventListener('click', this.handleStopClick);
this.elements.singleSweepBtn?.addEventListener('click', this.handleSingleSweepClick);
// Initial status update
this.updateStatus();
// Poll status every 2 seconds
this.statusInterval = setInterval(this.updateStatus, 2000);
this.isInitialized = true;
console.log('AcquisitionManager initialized');
}
async handleStartClick() {
try {
this.setButtonLoading(this.elements.startBtn, true);
const response = await fetch('/api/v1/acquisition/start', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
const result = await response.json();
if (result.success) {
this.notifications.show(result.message, 'success');
await this.updateStatus();
} else {
this.notifications.show(result.error || 'Failed to start acquisition', 'error');
}
} catch (error) {
console.error('Error starting acquisition:', error);
this.notifications.show('Failed to start acquisition', 'error');
} finally {
this.setButtonLoading(this.elements.startBtn, false);
}
}
async handleStopClick() {
try {
this.setButtonLoading(this.elements.stopBtn, true);
const response = await fetch('/api/v1/acquisition/stop', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
const result = await response.json();
if (result.success) {
this.notifications.show(result.message, 'success');
await this.updateStatus();
} else {
this.notifications.show(result.error || 'Failed to stop acquisition', 'error');
}
} catch (error) {
console.error('Error stopping acquisition:', error);
this.notifications.show('Failed to stop acquisition', 'error');
} finally {
this.setButtonLoading(this.elements.stopBtn, false);
}
}
async handleSingleSweepClick() {
try {
this.setButtonLoading(this.elements.singleSweepBtn, true);
const response = await fetch('/api/v1/acquisition/single-sweep', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
const result = await response.json();
if (result.success) {
this.notifications.show(result.message, 'success');
await this.updateStatus();
} else {
this.notifications.show(result.error || 'Failed to trigger single sweep', 'error');
}
} catch (error) {
console.error('Error triggering single sweep:', error);
this.notifications.show('Failed to trigger single sweep', 'error');
} finally {
this.setButtonLoading(this.elements.singleSweepBtn, false);
}
}
async updateStatus() {
try {
const response = await fetch('/api/v1/acquisition/status');
const status = await response.json();
this.currentStatus = status;
this.updateUI(status);
} catch (error) {
console.error('Error getting acquisition status:', error);
this.updateUI({
running: false,
paused: false,
continuous_mode: true,
sweep_count: 0
});
}
}
updateUI(status) {
// Update status text and indicator
let statusText = 'Idle';
let statusClass = 'status-indicator__dot--idle';
if (status.running) {
if (status.paused) {
statusText = 'Stopped';
statusClass = 'status-indicator__dot--paused';
} else {
statusText = 'Running';
statusClass = 'status-indicator__dot--running';
}
}
if (this.elements.statusText) {
this.elements.statusText.textContent = statusText;
}
if (this.elements.statusDot) {
this.elements.statusDot.className = `status-indicator__dot ${statusClass}`;
}
// Update mode text
if (this.elements.modeText) {
this.elements.modeText.textContent = status.continuous_mode ? 'Continuous' : 'Single';
}
// Update button states
if (this.elements.startBtn) {
this.elements.startBtn.disabled = status.running && !status.paused;
}
if (this.elements.stopBtn) {
this.elements.stopBtn.disabled = !status.running || status.paused;
}
if (this.elements.singleSweepBtn) {
this.elements.singleSweepBtn.disabled = !status.running;
}
// Update sweep count in header if available
const sweepCountEl = document.getElementById('sweepCount');
if (sweepCountEl) {
sweepCountEl.textContent = status.sweep_count || 0;
}
}
setButtonLoading(button, loading) {
if (!button) return;
if (loading) {
button.disabled = true;
button.classList.add('loading');
const icon = button.querySelector('i');
if (icon) {
icon.setAttribute('data-lucide', 'loader-2');
icon.style.animation = 'spin 1s linear infinite';
// Re-initialize lucide for the changed icon
if (window.lucide) {
window.lucide.createIcons();
}
}
} else {
button.disabled = false;
button.classList.remove('loading');
const icon = button.querySelector('i');
if (icon) {
icon.style.animation = '';
// Restore original icon
const buttonId = button.id;
const originalIcons = {
'startBtn': 'play',
'stopBtn': 'square',
'singleSweepBtn': 'zap'
};
const originalIcon = originalIcons[buttonId];
if (originalIcon) {
icon.setAttribute('data-lucide', originalIcon);
if (window.lucide) {
window.lucide.createIcons();
}
}
}
}
}
// Public method to trigger single sweep programmatically
async triggerSingleSweep() {
return await this.handleSingleSweepClick();
}
// Public method to get current acquisition status
isRunning() {
return this.currentStatus.running && !this.currentStatus.paused;
}
destroy() {
if (this.statusInterval) {
clearInterval(this.statusInterval);
}
// Remove event listeners
this.elements?.startBtn?.removeEventListener('click', this.handleStartClick);
this.elements?.stopBtn?.removeEventListener('click', this.handleStopClick);
this.elements?.singleSweepBtn?.removeEventListener('click', this.handleSingleSweepClick);
this.isInitialized = false;
console.log('AcquisitionManager destroyed');
}
}