Files
vna_system/vna_system/web_ui/static/js/modules/acquisition.js
T

207 lines
7.3 KiB
JavaScript

/**
* Acquisition Control Module
* Handles VNA data acquisition control via REST API
*/
import { setButtonLoading } from './utils.js';
import { apiGet, apiPost } from './api-client.js';
import { API, TIMING, NOTIFICATION_TYPES } from './constants.js';
const { SUCCESS, ERROR } = NOTIFICATION_TYPES;
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 periodically
this.statusInterval = setInterval(this.updateStatus, TIMING.STATUS_POLL_INTERVAL);
this.isInitialized = true;
console.log('AcquisitionManager initialized');
}
async handleStartClick() {
try {
const originalState = setButtonLoading(this.elements.startBtn, true);
const result = await apiPost(API.ACQUISITION.START);
if (result.success) {
this.notifications.show({ type: SUCCESS, title: 'Acquisition Started', message: result.message });
await this.updateStatus();
} else {
this.notifications.show({ type: ERROR, title: 'Start Failed', message: result.error || 'Failed to start acquisition' });
}
} catch (error) {
console.error('Error starting acquisition:', error);
this.notifications.show({ type: ERROR, title: 'Start Failed', message: 'Failed to start acquisition' });
} finally {
setButtonLoading(this.elements.startBtn, false, originalState);
}
}
async handleStopClick() {
try {
const originalState = setButtonLoading(this.elements.stopBtn, true);
const result = await apiPost(API.ACQUISITION.STOP);
if (result.success) {
this.notifications.show({ type: SUCCESS, title: 'Acquisition Stopped', message: result.message });
await this.updateStatus();
} else {
this.notifications.show({ type: ERROR, title: 'Stop Failed', message: result.error || 'Failed to stop acquisition' });
}
} catch (error) {
console.error('Error stopping acquisition:', error);
this.notifications.show({ type: ERROR, title: 'Stop Failed', message: 'Failed to stop acquisition' });
} finally {
setButtonLoading(this.elements.stopBtn, false, originalState);
}
}
async handleSingleSweepClick() {
try {
const originalState = setButtonLoading(this.elements.singleSweepBtn, true);
const result = await apiPost(API.ACQUISITION.SINGLE);
if (result.success) {
this.notifications.show({ type: SUCCESS, title: 'Single Sweep', message: result.message });
await this.updateStatus();
} else {
this.notifications.show({ type: ERROR, title: 'Single Sweep Failed', message: result.error || 'Failed to trigger single sweep' });
}
} catch (error) {
console.error('Error triggering single sweep:', error);
this.notifications.show({ type: ERROR, title: 'Single Sweep Failed', message: 'Failed to trigger single sweep' });
} finally {
setButtonLoading(this.elements.singleSweepBtn, false, originalState);
}
}
async updateStatus() {
try {
const status = await apiGet(API.ACQUISITION.STATUS);
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;
}
}
// 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');
}
}