Files
appRobotHoming/public/client.js
2026-03-17 08:15:25 +01:00

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();
})();