141 lines
4.6 KiB
JavaScript
141 lines
4.6 KiB
JavaScript
// app.js – gemeinsames JavaScript
|
||
console.log("MK Control JS geladen");
|
||
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
console.log('MK Control Frontend geladen');
|
||
|
||
const connectBtn = document.getElementById('connect-btn');
|
||
const connectSection = document.getElementById('connect-section');
|
||
const controlSection = document.getElementById('control-section');
|
||
const channelsContainer = document.getElementById('channels-container');
|
||
const stopAllBtn = document.getElementById('stop-all-btn');
|
||
|
||
if (!connectBtn) return; // Sicherstellen, dass wir auf der richtigen Seite sind
|
||
|
||
connectBtn.addEventListener('click', async () => {
|
||
connectBtn.disabled = true;
|
||
connectBtn.innerHTML = '<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span> Verbinde...';
|
||
|
||
try {
|
||
const response = await fetch('/api/connect', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' }
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
connectSection.style.display = 'none';
|
||
controlSection.style.display = 'block';
|
||
renderChannels();
|
||
alert('Verbunden! (Simulation)');
|
||
} else {
|
||
alert('Verbindung fehlgeschlagen: ' + (result.message || 'Unbekannter Fehler'));
|
||
}
|
||
} catch (err) {
|
||
console.error(err);
|
||
alert('Fehler bei der Verbindung: ' + err.message);
|
||
} finally {
|
||
connectBtn.disabled = false;
|
||
connectBtn.innerHTML = '<i class="bi bi-bluetooth me-2"></i> Mit Hub verbinden';
|
||
}
|
||
});
|
||
|
||
stopAllBtn.addEventListener('click', async () => {
|
||
if (!confirm('Wirklich alle Kanäle stoppen?')) return;
|
||
|
||
try {
|
||
const res = await fetch('/api/stop_all', { method: 'POST' });
|
||
const data = await res.json();
|
||
if (data.success) {
|
||
alert('Alle Kanäle gestoppt');
|
||
}
|
||
} catch (err) {
|
||
alert('Fehler beim Stoppen');
|
||
}
|
||
});
|
||
|
||
function renderChannels() {
|
||
channelsContainer.innerHTML = '';
|
||
|
||
if (!config.channels || config.channels.length === 0) {
|
||
channelsContainer.innerHTML = '<p class="text-center text-muted py-4">Keine Kanäle in der Konfiguration definiert.</p>';
|
||
return;
|
||
}
|
||
|
||
config.channels.forEach(channel => {
|
||
const col = document.createElement('div');
|
||
col.className = 'col-md-6 mb-4';
|
||
|
||
let controlHTML = '';
|
||
|
||
if (channel.type === 'motor') {
|
||
controlHTML = `
|
||
<label class="form-label">${channel.name} (${channel.port})</label>
|
||
<input type="range" class="form-range motor-slider"
|
||
min="-100" max="100" value="0" step="5"
|
||
data-port="${channel.port}">
|
||
<div class="text-center mt-1">
|
||
<span class="value-display">0 %</span>
|
||
</div>
|
||
`;
|
||
} else {
|
||
// Licht, Sound, Fogger → Toggle-Button
|
||
controlHTML = `
|
||
<label class="form-label">${channel.name} (${channel.port})</label>
|
||
<button class="btn btn-outline-secondary w-100 toggle-btn"
|
||
data-port="${channel.port}" data-state="off">
|
||
AUS
|
||
</button>
|
||
`;
|
||
}
|
||
|
||
col.innerHTML = `
|
||
<div class="card h-100">
|
||
<div class="card-body">
|
||
${controlHTML}
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
channelsContainer.appendChild(col);
|
||
});
|
||
|
||
// Event-Listener für Slider
|
||
document.querySelectorAll('.motor-slider').forEach(slider => {
|
||
const display = slider.parentElement.querySelector('.value-display');
|
||
slider.addEventListener('input', async () => {
|
||
const value = parseInt(slider.value) / 100;
|
||
display.textContent = `${slider.value} %`;
|
||
await sendControl(slider.dataset.port, value);
|
||
});
|
||
});
|
||
|
||
// Event-Listener für Toggle-Buttons
|
||
document.querySelectorAll('.toggle-btn').forEach(btn => {
|
||
btn.addEventListener('click', async () => {
|
||
const current = btn.dataset.state;
|
||
const newState = current === 'off' ? 'on' : 'off';
|
||
btn.dataset.state = newState;
|
||
btn.textContent = newState === 'on' ? 'EIN' : 'AUS';
|
||
btn.classList.toggle('btn-success', newState === 'on');
|
||
btn.classList.toggle('btn-outline-secondary', newState === 'off');
|
||
|
||
await sendControl(btn.dataset.port, newState === 'on' ? 1 : 0);
|
||
});
|
||
});
|
||
}
|
||
|
||
async function sendControl(port, value) {
|
||
try {
|
||
const res = await fetch('/api/control', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ port, value })
|
||
});
|
||
// Kann später Feedback geben
|
||
} catch (err) {
|
||
console.error('Steuerbefehl fehlgeschlagen:', err);
|
||
}
|
||
}
|
||
}); |