NEWS
Ausgabe Name des Senders
-
[{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":true,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"{0_userdata.0.enigma2.epg_html}"},"style":{"left":"73px","top":"53px","width":"1039px","height":"385px","border-width":"1px","border-style":"solid","border-color":"#ffffff","border-radius":"8px"},"widgetSet":"basic"}] -
Wert: <style> .e2-epg-table { width: 100%; border-collapse: collapse; font-family: sans-serif; font-size: 14px; color: #ffffff; } .e2-epg-table tr { border-bottom: 1px solid #444444; } .e2-epg-table tr:nth-child(even) { background-color: rgba(32,32,32,0.5); } .e2-epg-table td { padding: 10px 8px; vertical-align: top; } .e2-ch-name { font-weight: bold; color: #3498db; width: 33%; } .e2-time { color: #f1c40f; font-weight: bold; width: 33%; white-space: nowrap; } .e2-title { font-weight: bold; color: #ffffff; margin-bottom: 3px; } .e2-desc { color: #aaaaaa; font-size: 12px; line-height: 1.3; } </style> <table class="e2-epg-table"> </table>So richtig?
-
Wert: <style> .e2-epg-table { width: 100%; border-collapse: collapse; font-family: sans-serif; font-size: 14px; color: #ffffff; } .e2-epg-table tr { border-bottom: 1px solid #444444; } .e2-epg-table tr:nth-child(even) { background-color: rgba(32,32,32,0.5); } .e2-epg-table td { padding: 10px 8px; vertical-align: top; } .e2-ch-name { font-weight: bold; color: #3498db; width: 33%; } .e2-time { color: #f1c40f; font-weight: bold; width: 33%; white-space: nowrap; } .e2-title { font-weight: bold; color: #ffffff; margin-bottom: 3px; } .e2-desc { color: #aaaaaa; font-size: 12px; line-height: 1.3; } </style> <table class="e2-epg-table"> </table>So richtig?
das html element ist leer
<table class="e2-epg-table"> </table>das bedeutet das die folgende zeile nicht ausgeführt wird
epgData.events.forEach(event => {
weil epgData.events keine daten enthält oder kein array ist
mach mal im javascript editor davor einconsole.log(epgData.events);
im log, also im unteren bereich sollten dann daten oder nix ausgegeben werden.
alternativ auch
console.log(epgData); -
Wert: <style> .e2-epg-table { width: 100%; border-collapse: collapse; font-family: sans-serif; font-size: 14px; color: #ffffff; } .e2-epg-table tr { border-bottom: 1px solid #444444; } .e2-epg-table tr:nth-child(even) { background-color: rgba(32,32,32,0.5); } .e2-epg-table td { padding: 10px 8px; vertical-align: top; } .e2-ch-name { font-weight: bold; color: #3498db; width: 33%; } .e2-time { color: #f1c40f; font-weight: bold; width: 33%; white-space: nowrap; } .e2-title { font-weight: bold; color: #ffffff; margin-bottom: 3px; } .e2-desc { color: #aaaaaa; font-size: 12px; line-height: 1.3; } </style> <table class="e2-epg-table"> </table>So richtig?
der fehler liegt wahrscheinlich an der folgenden zeile
if (!event.sname || !event.event_title) return;
prüfe mal ob die attribute im event objekt tatsächlich so heißen.
evtl heißtevent.event_title
doch nur
event.title
?das selbe dann auch mit
event.event_start
event.event_description -
Wert: <style> .e2-epg-table { width: 100%; border-collapse: collapse; font-family: sans-serif; font-size: 14px; color: #ffffff; } .e2-epg-table tr { border-bottom: 1px solid #444444; } .e2-epg-table tr:nth-child(even) { background-color: rgba(32,32,32,0.5); } .e2-epg-table td { padding: 10px 8px; vertical-align: top; } .e2-ch-name { font-weight: bold; color: #3498db; width: 33%; } .e2-time { color: #f1c40f; font-weight: bold; width: 33%; white-space: nowrap; } .e2-title { font-weight: bold; color: #ffffff; margin-bottom: 3px; } .e2-desc { color: #aaaaaa; font-size: 12px; line-height: 1.3; } </style> <table class="e2-epg-table"> </table>So richtig?
die Box bzw. Openwebif liefert über /api/... eigentlich ein Json als Antwort (zumindest die VU+ Box hier). XML kommt über /web/...
Probier mal im Browser, ob die Antworten überhaupt kommen. Adresse anpassen nicht vergessen:
http://192.168.xx.xx/api/getservicessollte ähnliches liefern:
{ "services": [ { "servicereference": "1:7:1:0:0:0:0:0:0:0:FROM BOUQUET \"userbouquet.favourites.tv\" ORDER BY bouquet", "program": 0, "servicename": "Favourites (TV)", "pos": 1 }, { "servicereference": "1:7:1:0:0:0:0:0:0:0:FROM BOUQUET \"userbouquet.vti_192_000.tv\" ORDER BY bouquet", "program": 0, "servicename": "German Free SD", "pos": 2 }, { "servicereference": "1:7:1:0:0:0:0:0:0:0:FROM BOUQUET \"userbouquet.vti_192_001.tv\" ORDER BY bouquet", "program": 0, "servicename": "German Free HD", "pos": 3 },Die Epg Daten für jetzt kommen dann mit (1. Bouquet)
http://192.168.xx.xx/api/epgnow?bRef=1:7:1:0:0:0:0:0:0:0:{ "events": [ { "sname": ".", "title": null, "begin_timestamp": null, "now_timestamp": 1785390224, "sref": "1:0:1:300:7:85:C00000:0:0:0:", "id": null, "duration_sec": null, "shortdesc": null, "longdesc": null }, { "sname": "CGTN Documentary", "title": null, "begin_timestamp": null, "now_timestamp": 1785390224, "sref": "1:0:1:1B00:3FE:1:C00000:0:0:0:", "id": null, "duration_sec": null, "shortdesc": null, "longdesc": null }, { "sname": "Comedy Central HD.", "title": null, "begin_timestamp": null, "now_timestamp": 1785390224, "sref": "1:0:1:7000:436:1:C00000:0:0:0:", "id": null, "duration_sec": null, "shortdesc": null, "longdesc": null },... ], "result": true}danach oder gleich die Logausgaben von @oliverio einbauen
-
Guten morgen....Danke für die Hinweise und eure Antworten. Der entscheidente Tip kamm von @oliverio. Die Sendernamen zeigen an und auch der Titel der Sender. Und ja @ullij die Daten kommen alle an, die stehen in der API.
Nur wo es jetzt noch ein wenig hängt das ist die Uhrzeit da klemmt es noch.Geändert:
const startTime = new Date(event.start * 1000); const timeString = startTime.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }) + ' Uhr';Vorher:
const startTime = new Date(event.event_start * 1000); const timeString = startTime.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }) + ' Uhr'; -
Guten morgen....Danke für die Hinweise und eure Antworten. Der entscheidente Tip kamm von @oliverio. Die Sendernamen zeigen an und auch der Titel der Sender. Und ja @ullij die Daten kommen alle an, die stehen in der API.
Nur wo es jetzt noch ein wenig hängt das ist die Uhrzeit da klemmt es noch.Geändert:
const startTime = new Date(event.start * 1000); const timeString = startTime.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }) + ' Uhr';Vorher:
const startTime = new Date(event.event_start * 1000); const timeString = startTime.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }) + ' Uhr';Und in welcher Zeile ist das Problem?
Gibt es einen Fehler?
Wird in irgendeiner Zeile etwas nicht erwartetes zurückgegeben?Hast du log Ausgaben eingebaut.
Leider weiß ich nicht, wie die Daten tatsächlich aussehen.
Du hast zwar event.event_start geändert.
Oben sehe ich aber, dass es eher now_timestamp heißt.
Aber das sind die Daten von jemand anderen, keine Ahnung, wie es bei dir aussieht. -
Guten morgen....Danke für die Hinweise und eure Antworten. Der entscheidente Tip kamm von @oliverio. Die Sendernamen zeigen an und auch der Titel der Sender. Und ja @ullij die Daten kommen alle an, die stehen in der API.
Nur wo es jetzt noch ein wenig hängt das ist die Uhrzeit da klemmt es noch.Geändert:
const startTime = new Date(event.start * 1000); const timeString = startTime.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }) + ' Uhr';Vorher:
const startTime = new Date(event.event_start * 1000); const timeString = startTime.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }) + ' Uhr'; -
Der gesamte Code so wie er jetzt aussieht:
// --- KONFIGURATION GIGABLUE ENIGMA2 BOX--- const BOX_IP = 'XXX.XXX.XXX.XX'; // IP deiner Enigma2 Box bitte anpassen const TARGET_JSON_DP = '0_userdata.0.enigma2.epg_json'; //Datenpunkt Json const TARGET_HTML_DP = '0_userdata.0.enigma2.epg_html'; //Datenpunkt Html // --------------------- const axios = require('axios'); // Datenpunkte erstellen, falls sie fehlen await createStateAsync(TARGET_JSON_DP, { name: 'Enigma2 EPG JSON', type: 'string', role: 'json', read: true, write: false }); await createStateAsync(TARGET_HTML_DP, { name: 'Enigma2 EPG HTML für VIS', type: 'string', role: 'html', read: true, write: false }); // Holt vollautomatisch die exakte ID des ersten TV-Bouquets async function fetchValidBouquetRef() { try { const response = await axios.get(`http://${BOX_IP}/api/getallservices`, { timeout: 3000 }); if (response && response.data && response.data.services) { const services = response.data.services; // Fall 1: API liefert ein direktes Array if (Array.isArray(services) && services.length > 0) { return services[0].servicereference; } // Fall 2: API liefert ein verschachteltes Objekt if (services.servicereference) { return services.servicereference; } } } catch (e) { log(`Enigma2: Fehler beim automatischen Bouquet-Abruf: ${e.message}`, 'warn'); } return null; } function buildHtmlTable(epgData) { if (!epgData || !epgData.events || !Array.isArray(epgData.events) || epgData.events.length === 0) { return '<p style="color: #ff5252; padding: 10px;">Keine EPG-Daten empfangen. Bitte Bouquet-Einstellung prüfen.</p>'; } let html = ` <style> .e2-epg-table { width: 100%; border-collapse: collapse; font-family: sans-serif; font-size: 14px; color: #ffffff; } .e2-epg-table tr { border-bottom: 1px solid #444444; } .e2-epg-table tr:nth-child(even) { background-color: rgba(255,255,255,0.5); } .e2-epg-table td { padding: 10px 8px; vertical-align: top; } .e2-ch-name { font-weight: bold; color: #3498db; width: 33%; } .e2-time { color: #f1c40f; font-weight: bold; width: 33%; white-space: nowrap; } .e2-title { font-weight: bold; color: #ffffff; margin-bottom: 3px; } .e2-desc { color: #aaaaaa; font-size: 12px; line-height: 1.3; } </style> <table class="e2-epg-table"> `; epgData.events.forEach(event => { if (!event.sname || !event.title ) return; //const startTime = new Date(event.begin * 1000); //const timeString = startTime.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }) + ' Uhr'; //// // WICHTIG: Wert explizit in eine Ganzzahl konvertieren const timestampInSeconds = parseInt(event.start, 10); // Erst jetzt das Date-Objekt erzeugen const startDateObj = new Date(timestampInSeconds * 1000); // Formatieren der Ausgabe const timeString = startDateObj.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }) + ' Uhr'; const dateString = startDateObj.toLocaleDateString('de-DE'); //// html += ` <tr> <td class="e2-ch-name">${event.sname}</td> <td class="e2-time">${timeString} - ${dateString}</td> <td> <div class="e2-title">${event.title}</div> <div class="e2-desc">${event.description || ''}</div> </td> </tr> `; }); html += '</table>'; return html; } async function updateEPG() { try { // 1. Automatisch die korrekte, vom OpenWebif akzeptierte ID ermitteln const verifiedBref = await fetchValidBouquetRef(); if (!verifiedBref) { log('Enigma2 EPG abgebrochen: Es konnte keine gültige Bouquet-Referenz von der Box gelesen werden.', 'error'); return; } // 2. Abfrage mit dem vom OpenWebif exakt geforderten Parameter 'bRef' const url = `http://${BOX_IP}/api/epgnow?bRef=${encodeURIComponent(verifiedBref)}`; const response = await axios.get(url, { timeout: 5000 }); if (response && response.status === 200 && response.data) { const data = response.data; if (data.result === false) { log(`Enigma2 meldet Fehler im Payload: ${data.message || 'Unbekannt'}`, 'warn'); return; } // 1. JSON speichern await setStateAsync(TARGET_JSON_DP, JSON.stringify(data), true); // 2. HTML generieren und speichern const htmlTable = buildHtmlTable(data); await setStateAsync(TARGET_HTML_DP, htmlTable, true); log('Enigma2 EPG erfolgreich aktualisiert.', 'info'); } else { const status = response ? response.status : 'Keine Antwort'; log(`Enigma2 HTTP-Fehler: Status ${status}`, 'warn'); } } catch (error) { log(`Enigma2 EPG-Abruf fehlgeschlagen: ${error.message}`, 'warn'); } } // Trigger: Alle 15 Minuten schedule('*/15 * * * *', updateEPG); // Sofortstart beim Speichern updateEPG();So richtig?
-
Der gesamte Code so wie er jetzt aussieht:
// --- KONFIGURATION GIGABLUE ENIGMA2 BOX--- const BOX_IP = 'XXX.XXX.XXX.XX'; // IP deiner Enigma2 Box bitte anpassen const TARGET_JSON_DP = '0_userdata.0.enigma2.epg_json'; //Datenpunkt Json const TARGET_HTML_DP = '0_userdata.0.enigma2.epg_html'; //Datenpunkt Html // --------------------- const axios = require('axios'); // Datenpunkte erstellen, falls sie fehlen await createStateAsync(TARGET_JSON_DP, { name: 'Enigma2 EPG JSON', type: 'string', role: 'json', read: true, write: false }); await createStateAsync(TARGET_HTML_DP, { name: 'Enigma2 EPG HTML für VIS', type: 'string', role: 'html', read: true, write: false }); // Holt vollautomatisch die exakte ID des ersten TV-Bouquets async function fetchValidBouquetRef() { try { const response = await axios.get(`http://${BOX_IP}/api/getallservices`, { timeout: 3000 }); if (response && response.data && response.data.services) { const services = response.data.services; // Fall 1: API liefert ein direktes Array if (Array.isArray(services) && services.length > 0) { return services[0].servicereference; } // Fall 2: API liefert ein verschachteltes Objekt if (services.servicereference) { return services.servicereference; } } } catch (e) { log(`Enigma2: Fehler beim automatischen Bouquet-Abruf: ${e.message}`, 'warn'); } return null; } function buildHtmlTable(epgData) { if (!epgData || !epgData.events || !Array.isArray(epgData.events) || epgData.events.length === 0) { return '<p style="color: #ff5252; padding: 10px;">Keine EPG-Daten empfangen. Bitte Bouquet-Einstellung prüfen.</p>'; } let html = ` <style> .e2-epg-table { width: 100%; border-collapse: collapse; font-family: sans-serif; font-size: 14px; color: #ffffff; } .e2-epg-table tr { border-bottom: 1px solid #444444; } .e2-epg-table tr:nth-child(even) { background-color: rgba(255,255,255,0.5); } .e2-epg-table td { padding: 10px 8px; vertical-align: top; } .e2-ch-name { font-weight: bold; color: #3498db; width: 33%; } .e2-time { color: #f1c40f; font-weight: bold; width: 33%; white-space: nowrap; } .e2-title { font-weight: bold; color: #ffffff; margin-bottom: 3px; } .e2-desc { color: #aaaaaa; font-size: 12px; line-height: 1.3; } </style> <table class="e2-epg-table"> `; epgData.events.forEach(event => { if (!event.sname || !event.title ) return; //const startTime = new Date(event.begin * 1000); //const timeString = startTime.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }) + ' Uhr'; //// // WICHTIG: Wert explizit in eine Ganzzahl konvertieren const timestampInSeconds = parseInt(event.start, 10); // Erst jetzt das Date-Objekt erzeugen const startDateObj = new Date(timestampInSeconds * 1000); // Formatieren der Ausgabe const timeString = startDateObj.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }) + ' Uhr'; const dateString = startDateObj.toLocaleDateString('de-DE'); //// html += ` <tr> <td class="e2-ch-name">${event.sname}</td> <td class="e2-time">${timeString} - ${dateString}</td> <td> <div class="e2-title">${event.title}</div> <div class="e2-desc">${event.description || ''}</div> </td> </tr> `; }); html += '</table>'; return html; } async function updateEPG() { try { // 1. Automatisch die korrekte, vom OpenWebif akzeptierte ID ermitteln const verifiedBref = await fetchValidBouquetRef(); if (!verifiedBref) { log('Enigma2 EPG abgebrochen: Es konnte keine gültige Bouquet-Referenz von der Box gelesen werden.', 'error'); return; } // 2. Abfrage mit dem vom OpenWebif exakt geforderten Parameter 'bRef' const url = `http://${BOX_IP}/api/epgnow?bRef=${encodeURIComponent(verifiedBref)}`; const response = await axios.get(url, { timeout: 5000 }); if (response && response.status === 200 && response.data) { const data = response.data; if (data.result === false) { log(`Enigma2 meldet Fehler im Payload: ${data.message || 'Unbekannt'}`, 'warn'); return; } // 1. JSON speichern await setStateAsync(TARGET_JSON_DP, JSON.stringify(data), true); // 2. HTML generieren und speichern const htmlTable = buildHtmlTable(data); await setStateAsync(TARGET_HTML_DP, htmlTable, true); log('Enigma2 EPG erfolgreich aktualisiert.', 'info'); } else { const status = response ? response.status : 'Keine Antwort'; log(`Enigma2 HTTP-Fehler: Status ${status}`, 'warn'); } } catch (error) { log(`Enigma2 EPG-Abruf fehlgeschlagen: ${error.message}`, 'warn'); } } // Trigger: Alle 15 Minuten schedule('*/15 * * * *', updateEPG); // Sofortstart beim Speichern updateEPG();So richtig?
Hey! Du scheinst an dieser Unterhaltung interessiert zu sein, hast aber noch kein Konto.
Hast du es satt, bei jedem Besuch durch die gleichen Beiträge zu scrollen? Wenn du dich für ein Konto anmeldest, kommst du immer genau dorthin zurück, wo du zuvor warst, und kannst dich über neue Antworten benachrichtigen lassen (entweder per E-Mail oder Push-Benachrichtigung). Du kannst auch Lesezeichen speichern und Beiträge positiv bewerten, um anderen Community-Mitgliedern deine Wertschätzung zu zeigen.
Mit deinem Input könnte dieser Beitrag noch besser werden 💗
Registrieren Anmelden