NEWS
[Vorlage] E2 Kanalliste auslesen und per Alexa umschalten
-
Hallo an alle,
ich wollte hier mal meine Lösung zum Zappen mit Enigma2 Receivern vorstellen.
Es ist sicherlich nicht das schönste Script aber es tut was es sollIch war ewig auf der Suche nach einer Lösung und habe dann mittels MariaDB und JavaScript einen gangbaren Weg für mich gefunden.
Das Script extrahiert per http die Bouquet- und Channellist als XML, fügt diese per SQL in eine Datenbank ein und erstellt automatisch ein Smart-Gerät für jeden Kanal.
Zum Zappen habe ich ein Script geschrieben, dass per SQL-Abfrage die Ref-ID des senders aus der Datenbank ausliest und diese im E2-Adapter an den Datenpunkt ZAP übergibt.
Vorraussetzungen zum Betrieb:
- MariaDB mit Nutzer und Rechten
- cURL
- SQL-Adapter
- Enigma2-Adapter
Hier das Script zum Erstellen der Kanäle:
//Datenbankname var datenbank = "iobroker"; //SQL-Adapter-Instanz var sqlInstanz = "sql.0"; //IP des Receivers var box = "xxx.xxx.xxx.xxx"; //Bouquet-Namen var bouquet = new Array("Lenny","Chefin","Kind"); //Identifier für Bouquets var ident = new Array("","PL",""); //Anzahl Kanäle var idMax = 0; //Timeouts function Sleep (milliseconds) { return new Promise(resolve => setTimeout(resolve, milliseconds)); } //Instanzen müssen hier angepasst werden async function ChanUpdate () { //Script für ZAP ausschalten setState("javascript.0.scriptEnabled.Zappen", false); console.log("Zap OFF"); //Lösche Tabellen sendTo(sqlInstanz, 'query', 'DROP TABLE ' + datenbank + '.bouquet'); await Sleep (10); sendTo(sqlInstanz, 'query', 'DROP TABLE ' + datenbank + '.tv'); await Sleep (10); console.log("Tables gelöscht"); //Lösche alte Kanäle $('javascript.0.channels.*').each(function (id) { deleteState(id); }); await Sleep (10); console.log("Channels in iobroker gelöscht"); //Erstelle leere Tabellen sendTo(sqlInstanz, 'query', 'CREATE TABLE ' + datenbank + '.bouquet (id int NOT NULL AUTO_INCREMENT, e2servicereference varchar(255), e2servicename varchar(255), PRIMARY KEY (id));'); await Sleep (10) sendTo(sqlInstanz, 'query', 'CREATE TABLE ' + datenbank + '.tv (e2servicereference varchar(255), e2servicename varchar(255), bouquet varchar(255));'); await Sleep (10); console.log("Tables erstellt"); //Lese Bouquets aus exec('curl http://' + box + '/web/getservices > /home/iobroker/services.xml'); await Sleep (1000); console.log("Bouquets gelesen"); //Schreibe Bouquets in Datenbank sendTo(sqlInstanz, 'query', "LOAD XML LOCAL INFILE '/home/iobroker/services.xml' INTO TABLE " + datenbank + ".bouquet ROWS IDENTIFIED BY '<e2service>';"); await Sleep (1000) console.log("Bouquets geschrieben"); //Manipuliere Bouquet-Name sendTo(sqlInstanz, 'query', "UPDATE " + datenbank + ".bouquet SET e2servicereference = REPLACE(e2servicereference, ' ', '%20') WHERE INSTR(e2servicereference, ' ') > 0"); await Sleep (1000); sendTo(sqlInstanz, 'query', "UPDATE " + datenbank + ".bouquet SET e2servicereference = REPLACE(e2servicereference, '" + '"' + "', '%22') WHERE INSTR(e2servicereference, '" + '"' + "') > 0"); await Sleep (1000); console.log("Bouquets manipuliert"); //Erstelle Channel-XML für jedes Bouquet for (let i = 0; i < bouquet.length; i++) { console.log(bouquet[i]); sendTo(sqlInstanz, 'query', 'SELECT e2servicereference as channel FROM ' + datenbank + '.bouquet WHERE e2servicename LIKE "' + bouquet[i] + '";', function (result) { //Extrahiere services XML exec('curl http://' + box + '/web/getservices?sRef='+ result.result[0].channel + ' > /home/iobroker/services' + bouquet[i] + '.xml'); }); await Sleep (1000); console.log(bouquet[i] + " xml geschrieben"); //Importiere xml sendTo(sqlInstanz, 'query', "LOAD XML LOCAL INFILE '/home/iobroker/services" + bouquet[i] + ".xml' INTO TABLE " + datenbank + ".tv ROWS IDENTIFIED BY '<e2service>' SET bouquet = '" + ident[i] + "';"); await Sleep (1000); console.log(bouquet[i] + " in DB geschrieben"); //Manipuliere Kanalnamen sendTo(sqlInstanz, 'query', "UPDATE " + datenbank + ".tv SET e2servicename = REPLACE(e2servicename, '.', ' ') WHERE INSTR(e2servicename, '.') > 0"); await Sleep (100); sendTo(sqlInstanz, 'query', "UPDATE " + datenbank + ".tv SET e2servicename = REPLACE(e2servicename, 'III', '3') WHERE INSTR(e2servicename, 'III') > 0"); await Sleep (100) sendTo(sqlInstanz, 'query', "UPDATE " + datenbank + ".tv SET e2servicename = REPLACE(e2servicename, 'II', '2') WHERE INSTR(e2servicename, 'II') > 0"); await Sleep (100) console.log(bouquet[i] + " Channels manipuliert"); } //Füge index hinzu sendTo(sqlInstanz, 'query', "ALTER TABLE " + datenbank + ".tv ADD id INT AUTO_INCREMENT PRIMARY KEY;"); await Sleep (100); sendTo(sqlInstanz, 'query', "UPDATE " + datenbank + ".tv SET e2servicename=CONCAT(e2servicename, ' ', bouquet);"); await Sleep (100); console.log("Index geschrieben"); //Erstelle Kanäle sendTo(sqlInstanz, 'query', 'SELECT COUNT(*) as idMax FROM ' + datenbank + '.tv', function (result) { idMax = result.result[0].idMax; console.log (idMax); }); await Sleep (100); console.log (idMax); for (let j = 1; j < idMax; j++) { sendTo(sqlInstanz, 'query', 'SELECT e2servicename as channel FROM ' + datenbank + '.tv WHERE id = ' + j, function (result) { var kanal = result.result[0].channel; console.log(kanal); createState("javascript.0.channels." + kanal, false, { read: true, write: true, desc: kanal, type: "boolean", def: false, role: "switch", smartName: { 'de': kanal}, }); }); await Sleep (10); }; console.log("Channels in iobroker geschrieben"); //Script für ZAP einschalten setState("javascript.0.scriptEnabled.Zappen", true); console.log("ZAP on"); } ChanUpdate();
Im Script müssen die Variablen angepasst werden.
Das erste Array für Bouquet-Namen muss ausgefüllt werden!
Da müssen einfach eure Bouquet-Namen rein.
Das Identifier-Array muss um die Anzahl euer Bouquet-Einträge erweitert werden. Dieses Array dient dazu um Kanäle eindeutig zu identifizieren.
Mein Frau ist gebürtige Polin und deswegen haben wir auch polnische Sender. Da Sender wie z.B. TNT auch in anderen Ländern verfügbar sind, gibt es den Identifier. Das Gerät heißt dann z.B. bei mir "TNT Film HD" und bei meiner Frau "TNT Film HD PL".Hier mein Zap-Script:
//Datenbankname var datenbank = "iobroker"; //Adapter-Instanz var sqlInstanz = "sql.0"; //Trigger auf alle Objekte im Ordner Channel on({id: new RegExp("javascript\.0\.channels\.[a-zA-Z0-9]+"), change:"any"}, function (obj) { var value = obj.state.val; var oldValue = obj.oldState.val; //Name des geänderten Objektes auslesen var str = obj.common.name; //Name in Array einlesen var channel = str.split('.'); //Referenz-ID des gewählten Senders suchen und umschalten sendTo(sqlInstanz, 'query', 'SELECT e2servicereference as channel FROM ' + datenbank + '.tv WHERE e2servicename = "' + channel[3] + '"', function (result) { setState("enigma2.0.command.ZAP", result.result[0].channel); break; }); });
Ich bin nicht so der Erklär-Bär, aber hoffe dass ich damit einigen helfen konnte.
Fragen einfach hier rein -
Es funktioniert leider nicht , aber erstmal eine gute Idee !!
setState habe ich Auskommentiert , sonst wird das Script sofort beim Start beendet
Ich denke mal nach dem Einlesen willst du das Script dann ausschalten , aber dann wäre der Wert falsch .
.
Mußte das Script mehrmals starten , damit dann die Tabelle erstellt bzw. auch dann die Datenpunkte erzeugt werden , sind auch ein haufen Warn enthalten ..
Nach dem schalten vom Datenpunkt kommt nur eine Warn und es wird kein Programm geschaltet .Hier der Log :
-
Das Script zum Zappen hat "break" im Code. My fault
Ich habe noch eine Case-Abfrage drin, welcher echo dot anfragt und damit wird bestimmt welcher Receiver umschaltet.
Lösche mal das break;Zurück zum Problem:
Es ist möglich, dass du die Zeiten der Timeouts erhöhen musst. Beim ersten Durchlauf müssen auf jeden Fall Fehler auftauchen da die Tables ja nicht existieren. (Da könnte man noch ein Abfangen des Fehlers einbauen).Edit:
Das erste Script heißt Channel-Update bei mir. Wenn du es Zappen genannt hast, dann wird es natürlich beendet. das zweite Script ist Zappen -
@LennyCole sagte in [Vorlage] Enigma2 Kanalliste auslesen und Geräte erstellen:
Lösche mal das break;
Funktioniert über die Datenpunkte
Ahh , deshalb " scriptEnabled " habe mich schon gewundern , sollte für das andere Script sein .
Besser wäre dann scriptEnabled true zu für Zappen setzen wenn alle Datenpunkte erzeugt sind ,weil wenn nichts erzeugt wird setzt er dann Ihn zum Schluss trotzdem auf true .
War nicht gerade schön das er alle beim erstellen Duchgezappt hat ( habe gerade den Fernseher an ).. da ja auf any gehört wird mit deinem Zapper Script , wo er noch beim erstellen der Datenpunkte warDas Script Channel-Update sollte auch lieber dannach ausgeschaltet werden , da es beim Neustart vom System oder wenn Javascript abschmiert dann anschließend dein Programm gestartet wird .
-
Dann lass uns das Script perfektionieren mit Hilfe des Forums
EDIT:
Ich schrieb, dass eventuell die Timeouts angepasst werden müssen!
Bei mir ist Zap aus, dann werden channels gelöscht und neu geschrieben und dann ist Zap wieder an.Ich bin leider noch nicht so mit callbacks bei JavaScript involviert um es wirklich asynchron laufen zu lassen. Sollte es bei Dir zappen, dann ist entweder das Script beim Channel-Update nicht aus, oder du musst die Timeouts erhöhen bis keine Fehlermedung mehr zu sehen ist