137 lines
5.2 KiB
JavaScript
Executable File
137 lines
5.2 KiB
JavaScript
Executable File
(function(){
|
|
const logEl = document.getElementById('log');
|
|
const connEl = document.getElementById('conn');
|
|
|
|
function append(line){
|
|
const now = new Date().toISOString();
|
|
logEl.value += `[${now}] ${line}
|
|
`;
|
|
logEl.scrollTop = logEl.scrollHeight;
|
|
}
|
|
|
|
async function refreshStatus(){
|
|
try{
|
|
const res = await fetch('/api/status');
|
|
const st = await res.json();
|
|
if (st.connected){ connEl.textContent = 'verbunden'; connEl.className = 'badge ok'; }
|
|
else if (st.lastError){ connEl.textContent = 'fehler'; connEl.className = 'badge err'; }
|
|
else { connEl.textContent = 'getrennt'; connEl.className = 'badge warn'; }
|
|
}catch(e){ connEl.textContent = 'unbekannt'; connEl.className = 'badge'; }
|
|
}
|
|
|
|
function processDataShortenPosition(data){
|
|
if(data?.text){
|
|
try{
|
|
let obj = JSON.parse(data.text);
|
|
if(obj?.position){
|
|
obj.position.x = parseFloat(obj.position.x.toFixed(3));
|
|
obj.position.y = parseFloat(obj.position.y.toFixed(3));
|
|
obj.position.z = parseFloat(obj.position.z.toFixed(3));
|
|
obj.position.a = parseFloat(obj.position.a.toFixed(3));
|
|
obj.position.b = parseFloat(obj.position.b.toFixed(3));
|
|
obj.position.c = parseFloat(obj.position.c.toFixed(3));
|
|
}
|
|
if(obj?.motorCounts){
|
|
obj.motorCounts.x = parseFloat(obj.motorCounts.x.toFixed(3));
|
|
obj.motorCounts.y = parseFloat(obj.motorCounts.y.toFixed(3));
|
|
obj.motorCounts.z = parseFloat(obj.motorCounts.z.toFixed(3));
|
|
obj.motorCounts.a = parseFloat(obj.motorCounts.a.toFixed(3));
|
|
obj.motorCounts.b = parseFloat(obj.motorCounts.b.toFixed(3));
|
|
obj.motorCounts.c = parseFloat(obj.motorCounts.c.toFixed(3));
|
|
if(obj.motorCounts.e !== undefined) obj.motorCounts.e = parseFloat(obj.motorCounts.e.toFixed(3));
|
|
}
|
|
return "text: " + JSON.stringify(obj);
|
|
}catch(e){
|
|
return "text: " + data.text;
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
function connectSSE(){
|
|
const es = new EventSource('/api/events');
|
|
es.onmessage = (ev)=>{
|
|
try{
|
|
const p = JSON.parse(ev.data);
|
|
if (p.level === 'msg' && p.data?.text !== 'Ping') append(`WSS → ${processDataShortenPosition(p.data)}`);
|
|
//if (p.level === 'msg') append(`WSS → ${processDataShortenPosition(p.data)}`);
|
|
else if (p.level === 'tx') append(`TX → ${JSON.stringify(p.data)}`);
|
|
else append(`${p.level?.toUpperCase?.()}: ${p.message}`);
|
|
}catch{ append(ev.data); }
|
|
};
|
|
es.onerror = ()=>{
|
|
append('SSE Fehler/unterbrochen. Versuche neu zu verbinden…');
|
|
setTimeout(connectSSE, 2000);
|
|
};
|
|
}
|
|
|
|
function bindButtons(){
|
|
document.querySelectorAll('button[data-cmd]').forEach(btn =>{
|
|
btn.addEventListener('click', async () =>{
|
|
const cmd = btn.getAttribute('data-cmd');
|
|
|
|
let payload = null;
|
|
const payloadSelector = btn.getAttribute('data-payload');
|
|
if (payloadSelector) {
|
|
const field = document.querySelector(payloadSelector);
|
|
if (field) payload = field.value;
|
|
}
|
|
|
|
try{
|
|
const res = await fetch('/api/send', {
|
|
method:'POST', headers:{ 'Content-Type':'application/json' },
|
|
body: JSON.stringify({ cmd, payload })
|
|
});
|
|
const data = await res.json();
|
|
if(!res.ok){ append(`FEHLER ${res.status}: ${data.error || 'Unbekannt'}`); }
|
|
else { append(`Sende: ${cmd}`); }
|
|
}catch(err){ append('FEHLER: ' + (err?.message || err)); }
|
|
});
|
|
});
|
|
}
|
|
|
|
async function loadLatestSnapshot() {
|
|
try {
|
|
const res = await fetch('/api/latest-snapshot');
|
|
if (!res.ok) throw new Error('Fehler beim Laden des Snapshots');
|
|
let data;
|
|
if (res.headers.get('content-type')?.includes('application/json')) {
|
|
data = await res.json();
|
|
} else {
|
|
const csvData = await res.text();
|
|
// Fallback: filename aus dem Pfad oder unbekannt, mtime jetzt
|
|
data = { filename: 'latest.csv', mtime: new Date().toISOString(), content: csvData };
|
|
}
|
|
const infoEl = document.getElementById('snapshot-info');
|
|
const tableEl = document.getElementById('snapshot-table');
|
|
|
|
// Info anzeigen
|
|
const mtime = new Date(data.mtime).toLocaleString();
|
|
infoEl.textContent = `Datei: ${data.filename} | Erstellt: ${mtime}`;
|
|
|
|
// CSV parsen und Tabelle bauen
|
|
const lines = data.content.trim().split('\n');
|
|
if (lines.length === 0) {
|
|
tableEl.innerHTML = '<tr><td>Keine Daten</td></tr>';
|
|
return;
|
|
}
|
|
const headers = lines[0].split(',');
|
|
let html = '<thead><tr>' + headers.map(h => `<th>${h.trim()}</th>`).join('') + '</tr></thead><tbody>';
|
|
for (let i = 1; i < lines.length; i++) {
|
|
const cells = lines[i].split(',');
|
|
html += '<tr>' + cells.map(c => `<td>${c.trim()}</td>`).join('') + '</tr>';
|
|
}
|
|
html += '</tbody>';
|
|
tableEl.innerHTML = html;
|
|
} catch (err) {
|
|
document.getElementById('snapshot-info').textContent = 'Fehler: ' + err.message;
|
|
document.getElementById('snapshot-table').innerHTML = '';
|
|
}
|
|
}
|
|
|
|
bindButtons();
|
|
connectSSE();
|
|
refreshStatus();
|
|
loadLatestSnapshot();
|
|
})();
|