Skip to content

Commit 0e65e05

Browse files
committed
Applications can run after starting LSL by any protocol.
1 parent 9fb2f3c commit 0e65e05

File tree

2 files changed

+63
-11
lines changed

2 files changed

+63
-11
lines changed

app.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,30 @@ def event_stream():
7676

7777
return Response(event_stream(), mimetype="text/event-stream")
7878

79+
@app.route('/launch_app', methods=['POST'])
80+
def launch_application():
81+
if not connection_manager or not connection_manager.stream_active:
82+
return jsonify({'status': 'error', 'message': 'No active stream'}), 400
83+
84+
data = request.get_json()
85+
app_name = data.get('app')
86+
87+
if not app_name:
88+
return jsonify({'status': 'error', 'message': 'No application specified'}), 400
89+
90+
try:
91+
# Here we'll use subprocess to launch the application script
92+
import subprocess
93+
import sys
94+
95+
python_exec = sys.executable # Determine the correct Python executable
96+
subprocess.Popen([python_exec, f"{app_name}.py"]) # Launch the application script in a separate process
97+
98+
return jsonify({'status': 'success', 'message': f'Launched {app_name}'})
99+
except Exception as e:
100+
logging.error(f"Error launching {app_name}: {str(e)}")
101+
return jsonify({'status': 'error', 'message': str(e)}), 500
102+
79103
@app.route('/connect', methods=['POST'])
80104
def connect_device():
81105
global connection_manager, connection_thread, stream_active

templates/index.html

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,30 +127,39 @@ <h2 class="text-xl font-semibold text-gray-700 dark:text-gray-200">Applications<
127127
</footer>
128128
<script>
129129
const apps = [
130-
{ title: 'ECG with Heart Rate', icon: 'fa-heartbeat', color: 'cyan' },
131-
{ title: 'EMG with Envelope', icon: 'fa-wave-square', color: 'red' },
132-
{ title: 'EOG with Blinks', icon: 'fa-chart-line', color: 'purple' },
133-
{ title: 'EEG with FFT', icon: 'fa-hand-holding-water', color: 'green' },
134-
{ title: 'EEG Tug of War game', icon: 'fa-brain', color: 'yellow' },
135-
{ title: 'EEG Beetle Game', icon: 'fa-eye', color: 'pink' },
136-
{ title: 'EOG Keystroke Emualtor', icon: 'fa-lungs', color: 'blue' },
137-
{ title: 'GUI Visualization', icon: 'fa-heart-pulse', color: 'orange' },
138-
{ title: 'CSV Plotter', icon: 'fa-thermometer-half', color: 'teal' },
130+
{ title: 'ECG with Heart Rate', icon: 'fa-heartbeat', color: 'cyan', script: 'heartbeat_ecg' },
131+
{ title: 'EMG with Envelope', icon: 'fa-wave-square', color: 'red', script: 'emgenvelope' },
132+
{ title: 'EOG with Blinks', icon: 'fa-eye', color: 'purple', script: 'eog' },
133+
{ title: 'EEG with FFT', icon: 'fa-brain', color: 'green', script: 'ffteeg' },
134+
{ title: 'EEG Tug of War game', icon: 'fa-gamepad', color: 'yellow', script: 'game' },
135+
{ title: 'EEG Beetle Game', icon: 'fa-bug', color: 'pink', script: 'beetle' },
136+
{ title: 'EOG Keystroke Emulator', icon: 'fa-keyboard', color: 'blue', script: 'keystroke' },
137+
{ title: 'GUI Visualization', icon: 'fa-chart-bar', color: 'orange', script: 'gui' },
138+
{ title: 'CSV Plotter', icon: 'fa-chart-line', color: 'teal', script: 'csvplotter' },
139139
];
140140

141141
const appGrid = document.getElementById('app-grid');
142142
apps.forEach(app => {
143143
const card = document.createElement('div');
144-
card.className = 'bg-gradient-to-b from-white to-gray-50 dark:from-gray-700 dark:to-gray-800 rounded-xl shadow border hover:shadow-lg transition duration-300 dark:border-gray-700';
144+
card.className = 'bg-gradient-to-b from-white to-gray-50 dark:from-gray-700 dark:to-gray-800 rounded-xl shadow border hover:shadow-lg transition duration-300 dark:border-gray-700 cursor-pointer';
145145
card.innerHTML = `
146146
<div class="p-4">
147147
<div class="w-full h-32 bg-${app.color}-100 dark:bg-${app.color}-900 rounded-lg flex items-center justify-center mb-4">
148148
<i class="fas ${app.icon} text-4xl text-${app.color}-600 dark:text-${app.color}-300"></i>
149149
</div>
150150
<h3 class="text-lg font-semibold text-gray-800 dark:text-gray-200 mb-1">${app.title}</h3>
151-
<p class="text-sm text-gray-600 dark:text-gray-400">Sample description for ${app.title}</p>
151+
<p class="text-sm text-gray-600 dark:text-gray-400">Click to launch ${app.title}</p>
152152
</div>
153153
`;
154+
155+
card.addEventListener('click', () => {
156+
if (!isConnected) {
157+
showAlert('Please start LSL Stream first by any protocol (USB/WIFI/BLE)');
158+
return;
159+
}
160+
launchApplication(app.script);
161+
});
162+
154163
appGrid.appendChild(card);
155164
});
156165

@@ -462,6 +471,25 @@ <h3 class="text-lg font-semibold text-gray-800 dark:text-gray-200 mb-1">${app.ti
462471
startConsoleUpdates();
463472
}
464473

474+
function launchApplication(appName) {
475+
fetch('/launch_app', {
476+
method: 'POST',
477+
headers: { 'Content-Type': 'application/json' },
478+
body: JSON.stringify({ app: appName })
479+
})
480+
.then(response => response.json())
481+
.then(data => {
482+
if (data.status === 'success') {
483+
// showStatus(`Launched ${appName} application`, 'fa-check-circle', 'text-green-500');
484+
} else {
485+
showAlert(`Failed to launch ${appName}: ${data.message}`);
486+
}
487+
})
488+
.catch(error => {
489+
showAlert(`Error launching ${appName}: ${error.message}`);
490+
});
491+
}
492+
465493
// Handle disconnect button
466494
disconnectBtn.addEventListener('click', async () => {
467495
try {

0 commit comments

Comments
 (0)