diff --git a/static/discovery.js b/static/discovery.js
index 00e12b8..26171b4 100644
--- a/static/discovery.js
+++ b/static/discovery.js
@@ -1,6 +1,8 @@
// Simplified Discovery Integration
// Updated for simplified signal names + tags architecture
+console.log('=== DISCOVERY.JS FILE LOADED - START ===');
+
class SimplifiedProtocolDiscovery {
constructor() {
this.currentScanId = 'simplified-scan-123';
@@ -8,74 +10,99 @@ class SimplifiedProtocolDiscovery {
}
init() {
- this.bindDiscoveryEvents();
+ console.log('Discovery.js: init() called');
+ try {
+ this.bindDiscoveryEvents();
+ console.log('Discovery.js: bindDiscoveryEvents() completed successfully');
+ } catch (error) {
+ console.error('Discovery.js: Error in init():', error);
+ }
}
bindDiscoveryEvents() {
+ console.log('Binding discovery events...');
+
// Discovery scan button
const startScanBtn = document.getElementById('start-discovery-scan');
+ console.log('Start scan button:', startScanBtn);
if (startScanBtn) {
startScanBtn.addEventListener('click', () => {
+ console.log('Start Discovery Scan button clicked!');
this.startDiscoveryScan();
});
+ } else {
+ console.error('Start scan button not found!');
}
+ // Check if discovery results container exists
+ const resultsContainer = document.getElementById('discovery-results');
+ console.log('Discovery results container during init:', resultsContainer);
+
// Auto-fill signal form from discovery
- document.addEventListener('click', (e) => {
- if (e.target.classList.contains('use-discovered-endpoint')) {
- this.useDiscoveredEndpoint(e.target.dataset.endpointId);
- }
- });
+ console.log('Setting up global click event listener for use-signal-btn');
+ try {
+ const self = this; // Capture 'this' context
+ document.addEventListener('click', function(e) {
+ console.log('Global click event fired, target:', e.target.tagName, 'classes:', e.target.className);
+ console.log('Target dataset:', e.target.dataset);
+
+ if (e.target.classList.contains('use-signal-btn')) {
+ console.log('Use This Signal button clicked!');
+ console.log('Signal index from dataset:', e.target.dataset.signalIndex);
+ self.useDiscoveredEndpoint(e.target.dataset.signalIndex);
+ } else {
+ console.log('Clicked element is not a use-signal-btn');
+ }
+ });
+ console.log('Global click event listener set up successfully');
+ } catch (error) {
+ console.error('Error setting up event listener:', error);
+ }
}
- async useDiscoveredEndpoint(endpointId) {
- console.log('Using discovered endpoint:', endpointId);
+ async useDiscoveredEndpoint(signalIndex) {
+ console.log('Using discovered endpoint with index:', signalIndex);
- // Mock endpoint data (in real implementation, this would come from discovery service)
- const endpoints = {
- 'device_001': {
- device_id: 'device_001',
- protocol_type: 'modbus_tcp',
- device_name: 'Water Pump Controller',
- address: '192.168.1.100',
- port: 502,
- data_point: 'Speed',
- protocol_address: '40001'
- },
- 'device_002': {
- device_id: 'device_002',
- protocol_type: 'opcua',
- device_name: 'Temperature Sensor',
- address: '192.168.1.101',
- port: 4840,
- data_point: 'Temperature',
- protocol_address: 'ns=2;s=Temperature'
- },
- 'device_003': {
- device_id: 'device_003',
- protocol_type: 'modbus_tcp',
- device_name: 'Pressure Transmitter',
- address: '192.168.1.102',
- port: 502,
- data_point: 'Pressure',
- protocol_address: '30001'
- }
- };
+ // Get the actual discovered endpoints from the mock scan
+ const discoveredEndpoints = await this.mockDiscoveryScan('192.168.1.0/24');
- const endpoint = endpoints[endpointId];
+ // Map signal index to endpoint
+ const endpoint = discoveredEndpoints[signalIndex];
if (!endpoint) {
- this.showNotification(`Endpoint ${endpointId} not found`, 'error');
+ this.showNotification(`Endpoint with index ${signalIndex} not found`, 'error');
return;
}
// Convert to simplified signal format
const signalData = this.convertEndpointToSignal(endpoint);
- // Auto-populate the signal form
- this.autoPopulateSignalForm(signalData);
+ // Auto-populate the signal form with retry logic
+ this.autoPopulateSignalFormWithRetry(signalData);
this.showNotification(`Endpoint ${endpoint.device_name} selected for signal creation`, 'success');
}
+
+ autoPopulateSignalFormWithRetry(signalData, retryCount = 0) {
+ console.log('Attempting to auto-populate signal form, attempt:', retryCount + 1);
+
+ if (typeof window.autoPopulateSignalForm === 'function') {
+ console.log('Found window.autoPopulateSignalForm, calling it...');
+ window.autoPopulateSignalForm(signalData);
+ } else {
+ console.error('autoPopulateSignalForm function not found');
+
+ // Retry after a delay if we haven't exceeded max retries
+ if (retryCount < 5) {
+ console.log(`Retrying in 500ms... (${retryCount + 1}/5)`);
+ setTimeout(() => {
+ this.autoPopulateSignalFormWithRetry(signalData, retryCount + 1);
+ }, 500);
+ } else {
+ console.error('Max retries exceeded, autoPopulateSignalForm function still not found');
+ this.showNotification('Error: Could not open signal form. Please ensure the protocol mapping system is loaded.', 'error');
+ }
+ }
+ }
convertEndpointToSignal(endpoint) {
// Generate human-readable signal name
@@ -120,25 +147,7 @@ class SimplifiedProtocolDiscovery {
}
- autoPopulateSignalForm(signalData) {
- console.log('Auto-populating signal form with:', signalData);
-
- // Ensure protocol mapping tab is active
- if (typeof showTab === 'function') {
- showTab('protocol-mapping');
- }
-
- // Use the simplified protocol mapping function
- if (typeof window.autoPopulateSignalForm === 'function') {
- // Add a small delay to ensure the tab is loaded
- setTimeout(() => {
- window.autoPopulateSignalForm(signalData);
- }, 100);
- } else {
- console.error('Simplified protocol mapping functions not loaded');
- this.showNotification('Protocol mapping system not available', 'error');
- }
- } // Start discovery scan
+ // Start discovery scan
async startDiscoveryScan() {
console.log('Starting discovery scan...');
@@ -249,6 +258,7 @@ class SimplifiedProtocolDiscovery {
return;
}
+ console.log('Found discovery results container:', resultsContainer);
resultsContainer.innerHTML = '
Discovery Results
';
suggestedSignals.forEach((signal, index) => {
@@ -274,13 +284,35 @@ class SimplifiedProtocolDiscovery {
});
// Add event listeners for use buttons
- resultsContainer.addEventListener('click', (e) => {
+ console.log('Adding event listener to results container');
+ console.log('Results container:', resultsContainer);
+ console.log('Results container ID:', resultsContainer.id);
+ console.log('Number of use-signal-btn elements:', resultsContainer.querySelectorAll('.use-signal-btn').length);
+
+ const clickHandler = (e) => {
+ console.log('Discovery results container clicked:', e.target);
+ console.log('Button classes:', e.target.classList);
+ console.log('Button tag name:', e.target.tagName);
if (e.target.classList.contains('use-signal-btn')) {
+ console.log('Use This Signal button clicked!');
const signalIndex = parseInt(e.target.dataset.signalIndex);
+ console.log('Signal index:', signalIndex);
const signal = suggestedSignals[signalIndex];
- this.autoPopulateSignalForm(signal);
+ console.log('Signal data:', signal);
+
+ // Use the global function directly
+ if (typeof window.autoPopulateSignalForm === 'function') {
+ window.autoPopulateSignalForm(signal);
+ } else {
+ console.error('autoPopulateSignalForm function not found!');
+ }
+ } else {
+ console.log('Clicked element is not a use-signal-btn');
}
- });
+ };
+
+ resultsContainer.addEventListener('click', clickHandler);
+ console.log('Event listener added to results container');
// Add "Apply All" button
const applyAllButton = document.createElement('button');
@@ -308,8 +340,20 @@ class SimplifiedProtocolDiscovery {
let successCount = 0;
let errorCount = 0;
+ let duplicateCount = 0;
+
+ // First, check which signals already exist
+ const existingSignals = await this.getExistingSignals();
+ const existingSignalNames = new Set(existingSignals.map(s => s.signal_name));
for (const signal of signals) {
+ // Skip if signal with same name already exists
+ if (existingSignalNames.has(signal.signal_name)) {
+ console.log(`⚠ Skipping duplicate signal: ${signal.signal_name}`);
+ duplicateCount++;
+ continue;
+ }
+
try {
const response = await fetch('/api/v1/dashboard/protocol-signals', {
method: 'POST',
@@ -322,9 +366,16 @@ class SimplifiedProtocolDiscovery {
if (data.success) {
successCount++;
console.log(`✓ Created signal: ${signal.signal_name}`);
+ // Add to existing set to prevent duplicates in same batch
+ existingSignalNames.add(signal.signal_name);
} else {
errorCount++;
console.error(`✗ Failed to create signal: ${signal.signal_name}`, data.detail);
+
+ // Check if it's a duplicate error
+ if (data.detail && data.detail.includes('already exists')) {
+ duplicateCount++;
+ }
}
} catch (error) {
errorCount++;
@@ -333,14 +384,40 @@ class SimplifiedProtocolDiscovery {
}
// Show results
- const message = `Created ${successCount} signals successfully. ${errorCount > 0 ? `${errorCount} failed.` : ''}`;
- this.showNotification(message, errorCount > 0 ? 'warning' : 'success');
+ let message = `Created ${successCount} signals successfully.`;
+ if (errorCount > 0) {
+ message += ` ${errorCount} failed.`;
+ }
+ if (duplicateCount > 0) {
+ message += ` ${duplicateCount} duplicates skipped.`;
+ }
+
+ const notificationType = errorCount > 0 ? 'warning' : (successCount > 0 ? 'success' : 'info');
+ this.showNotification(message, notificationType);
// Refresh the protocol signals display
if (typeof window.loadAllSignals === 'function') {
window.loadAllSignals();
}
}
+
+ // Get existing signals to check for duplicates
+ async getExistingSignals() {
+ try {
+ const response = await fetch('/api/v1/dashboard/protocol-signals');
+ const data = await response.json();
+
+ if (data.success) {
+ return data.signals || [];
+ } else {
+ console.error('Failed to get existing signals:', data.detail);
+ return [];
+ }
+ } catch (error) {
+ console.error('Error getting existing signals:', error);
+ return [];
+ }
+ }
// Tag-based signal search
async searchSignalsByTags(tags) {
@@ -363,6 +440,47 @@ class SimplifiedProtocolDiscovery {
}
}
+ // Clear all existing signals (for testing)
+ async clearAllSignals() {
+ if (!confirm('Are you sure you want to delete ALL protocol signals? This action cannot be undone.')) {
+ return;
+ }
+
+ try {
+ const existingSignals = await this.getExistingSignals();
+ let deletedCount = 0;
+
+ for (const signal of existingSignals) {
+ try {
+ const response = await fetch(`/api/v1/dashboard/protocol-signals/${signal.signal_id}`, {
+ method: 'DELETE'
+ });
+
+ const data = await response.json();
+
+ if (data.success) {
+ deletedCount++;
+ console.log(`✓ Deleted signal: ${signal.signal_name}`);
+ } else {
+ console.error(`✗ Failed to delete signal: ${signal.signal_name}`, data.detail);
+ }
+ } catch (error) {
+ console.error(`✗ Error deleting signal: ${signal.signal_name}`, error);
+ }
+ }
+
+ this.showNotification(`Deleted ${deletedCount} signals successfully.`, 'success');
+
+ // Refresh the protocol signals display
+ if (typeof window.loadAllSignals === 'function') {
+ window.loadAllSignals();
+ }
+ } catch (error) {
+ console.error('Error clearing signals:', error);
+ this.showNotification('Error clearing signals', 'error');
+ }
+ }
+
// Signal name suggestions based on device type
generateSignalNameSuggestions(deviceName, dataPoint) {
const baseName = `${deviceName} ${dataPoint}`;
@@ -462,9 +580,26 @@ class SimplifiedProtocolDiscovery {
}
// Global instance
+// Expose to window for global access
+window.SimplifiedProtocolDiscovery = SimplifiedProtocolDiscovery;
+
const simplifiedDiscovery = new SimplifiedProtocolDiscovery();
+window.simplifiedDiscovery = simplifiedDiscovery;
// Initialize when DOM is loaded
-document.addEventListener('DOMContentLoaded', function() {
- simplifiedDiscovery.init();
-});
\ No newline at end of file
+console.log('Discovery.js loaded - setting up DOMContentLoaded listener');
+
+// Check if DOM is already loaded
+if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', function() {
+ console.log('DOMContentLoaded event fired - Initializing SimplifiedProtocolDiscovery...');
+ window.simplifiedDiscovery.init();
+ console.log('SimplifiedProtocolDiscovery initialized successfully');
+ });
+} else {
+ console.log('DOM already loaded - Initializing SimplifiedProtocolDiscovery immediately...');
+ window.simplifiedDiscovery.init();
+ console.log('SimplifiedProtocolDiscovery initialized successfully');
+}
+
+console.log('=== DISCOVERY.JS FILE LOADED - END ===');
\ No newline at end of file
diff --git a/templates/simplified_protocol_signals.html b/templates/simplified_protocol_signals.html
index 3b3c217..d99132c 100644
--- a/templates/simplified_protocol_signals.html
+++ b/templates/simplified_protocol_signals.html
@@ -42,6 +42,23 @@
+
+
+
Discovery Results
+
Use discovered signals to quickly add them to your protocol mapping:
+
+
+
+
+
+
+
+
+
Popular Tags
@@ -136,7 +153,7 @@
-
-
+
+