Hallo Leute
Hallo erst mal von meiner Seite. Ich bin neu in Python und will mich da auch gar nicht so wahnsinnig viel mit machen. Ich habe da eine ganz spezielle Frage. Ich habe einen VU SOLO2 HD TV Receiver. Natürlich Linux, was aber kein Problem ist. Java und Co. gibt es für dieses Derivat leider nicht. Es gibt aber eine Weboberfläche die sich OpenWebIf nennt. Diese läuft, soweit ich das mit meiner geringen Python Kenntnis ausmachen kann, über Python. Das funktioniert auch alles super. Ich habe noch einen alten Samsung TV den ich über Python ansteuern kann. Also Programme umschalten, Lautstärke regeln usw. Und ich habe meine neue Freundin, die Alexa aus dem Hause Amazon. Ich weiß, das Thema ist viel diskutiert aber ich finde es erst mal klasse. Hab ich mir schon ewig gewünscht so eine Sprachbedienung. Zwar weniger für den Frenseher sondern für die anderen Dinge im Haushalt. Aber das ist ein anderes Thema. Ich möchte über den Amazon Echo den Fernseher bedienen. Ich weiß auch, dass es einen Haufen anderer Lösungen dafür gibt, ich möchte es aber trotzdem folgendermassen machen.
Amazon Echo -> IFTTT (WebRequest) -> Python WebFrontend auf der VU SOLO2 -> TV
Verrückt, ich weiß. Was mir fehlt ist der Python Schritt. Da kenne ich mich nicht so aus. Daher kann ich auch nicht so richtig einschätzen was auf meiner Box für ein WebFramework benutzt wird. Ich habe gesehen, dass es im Filesystem ein paar Verzeichnisse mit __init__.py und __init__.pyo gibt. Vielleicht könnt ihr mir da schon weiterhelfen. Wenn ich das Framework kenne, kann ich dann weitersuchen wie ich unter dem gleichen Framework ein neues Verzeichnis anlege mit einer einzelnen Webseite die die einzelnen Links zur TV Bedienung enthalten die ich dann per IFTTT steuern kann. Und ja, über die Sicherheit mache ich mir dann auch Gedanken.
Jetzt freue ich mich über eure Tipps wie ich erkennen kann welches Framework ich hier habe und vielleicht auch schon ein paar weiterführende Tips wie ich so eine Seite da einbinden kann.
Vielen Dank
Klüsi
Welches Framework nutzt meine VU SOLO2 Sat Receiver Box?
Die GUI nennt sich enigma2
https://github.com/openatv/enigma2
Aus www.i-have-a-dreambox.com gibt es ein paar Tutorials, wie man Plugins für e2 schreibt...
https://github.com/openatv/enigma2
Aus www.i-have-a-dreambox.com gibt es ein paar Tutorials, wie man Plugins für e2 schreibt...
So da bin ich wieder
Ich habe eine Menge heraus herausgefunden. Ich habe einen eigenen minimalen Controller erstellt und den in root.py eingebunden. In der render Funktion ksnn ich mit
ausgeben. Aber sobald ich hier mit html Code ankomme gibt es nur Fehler. Bei mir sieht das so aus :
So funktioniert es. Aber wenn ich anstatt dem hier, dass folgende verwende :
Bekomme ich nur Fehlermeldungen. Die Fehlermeldung habe ich gerade nicht zur Hand.
Vielen Dank
Kluesi
Ich habe eine Menge heraus herausgefunden. Ich habe einen eigenen minimalen Controller erstellt und den in root.py eingebunden. In der render Funktion ksnn ich mit
Code: Alles auswählen
Return """
Hallo Welt
"""
Code: Alles auswählen
from twisted.web import resource, http
class PrivateController(resource.Resource):
def __init__(self, session, path = ""):
resource.Resource.__init__(self)
self.session = session
def render(self, request):
request.setResponseCode(http.OK)
request.setHeader('Content-type', 'text/plain')
request.setHeader('charset', 'UTF-8')
return """
Mein eigener Controller
Request:
Methode: %s
Argumente: %s
""" % (request.method,request.args)
Code: Alles auswählen
return """
<html><body>Hallo</body></html>
"""
Vielen Dank
Kluesi
Zuletzt geändert von Anonymous am Sonntag 6. August 2017, 13:26, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
@kluesi: Den richtigen Content-Type senden, damit der Browser weiss was er damit machen soll.
So, ich habe zwei neue Teile hinzugefügt. Sie machen beide was sie sollen. Das eine stellt per Telnet Userprofile auf der Fritzbox um und das andere schaltet meinen Fernseher um. beides funktioniert. Am nächsten Tag jedoch reagiert das Webinterface nicht mehr. Auch nicht das reguläre OpenWebIf nicht mehr. Irgendetwas scheint hier nicht so ganz sauber zu sein. Wahrscheinlich brauche ich noch ein paar Sicherheitsmechanismen im Python Skript. Vielleicht wird irgendetwas nicht korrekt beendet, Speicher freigegeben, oder so. Könnt ihr mir da mal helfen?
Hier sind beide Skripte:
Vielen Dank
Hier sind beide Skripte:
Code: Alles auswählen
# -*- coding: utf-8 -*-
##############################################################################
# 2013 E2OpenPlugins #
# #
# This file is open source software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License version 2 as #
# published by the Free Software Foundation. #
# #
##############################################################################
from twisted.web import static, resource, http, server
import time
import socket
import base64
class kidsController(resource.Resource):
global ergebnis
global setProfile
def __init__(self, session, path = ""):
resource.Resource.__init__(self)
self.session = session
def setProfile(aProfile):
import getpass
import sys
import telnetlib
HOST = "192.168.0.254"
password = "###########"
tn = telnetlib.Telnet(HOST)
tn.read_until("password: ")
tn.write(password + "\n")
tn.read_until("# ")
ergebnis="-"
if aProfile == "ipad_korbin_off":
tn.write("ctlmgr_ctl w user settings/user2/filter_profile_UID filtprof853\n") # Korbin iPad off
if aProfile == "ipad_korbin_time":
tn.write("ctlmgr_ctl w user settings/user2/filter_profile_UID filtprof848\n") # Korbin iPad time
if aProfile == "ipad_korbin_free":
tn.write("ctlmgr_ctl w user settings/user2/filter_profile_UID filtprof850\n") # Korbin iPad free
if aProfile == "iphone_korbin_off":
tn.write("ctlmgr_ctl w user settings/user3/filter_profile_UID filtprof853\n") # Korbin iPhone off
if aProfile == "iphone_korbin_time":
tn.write("ctlmgr_ctl w user settings/user3/filter_profile_UID filtprof848\n") # Korbin iPhone time
if aProfile == "iphone_korbin_free":
tn.write("ctlmgr_ctl w user settings/user3/filter_profile_UID filtprof850\n") # Korbin iPhone free
if aProfile == "tablet_kendra_off":
tn.write("ctlmgr_ctl w user settings/user4/filter_profile_UID filtprof852\n") # Kendra Tablet off
if aProfile == "tablet_kendra_time":
tn.write("ctlmgr_ctl w user settings/user4/filter_profile_UID filtprof849\n") # Kendra Tablet time
if aProfile == "tablet_kendra_free":
tn.write("ctlmgr_ctl w user settings/user4/filter_profile_UID filtprof851\n") # Kendra Tablet free
tn.write("exit\n")
atext = tn.read_all()
tn.close()
return atext
def render(self, request):
abc = "-"
if "profile" in request.args.keys():
abc=setProfile(request.args["profile"][0])
request.setResponseCode(http.OK)
request.setHeader('Content-type', 'text/html')
request.setHeader('charset', 'UTF-8')
return """<html><body><b>Profile</b><br><br>
<a href="http://192.168.0.232/kids?profile=ipad_korbin_off">Korbin - iPad - OFF</a><br><br><br>
<a href="http://192.168.0.232/kids?profile=ipad_korbin_time">Korbin - iPad - TIME</a><br><br><br>
<a href="http://192.168.0.232/kids?profile=ipad_korbin_free">Korbin - iPad - FREE</a><br><br><br>
<a href="http://192.168.0.232/kids?profile=iphone_korbin_off">Korbin - iPhone - OFF</a><br><br><br>
<a href="http://192.168.0.232/kids?profile=iphone_korbin_time">Korbin - iPhone - TIME</a><br><br><br>
<a href="http://192.168.0.232/kids?profile=iphone_korbin_free">Korbin - iPhone - FREE</a><br><br><br>
<a href="http://192.168.0.232/kids?profile=tablet_kendra_off">Kendra - Tablet - OFF</a><br><br><br>
<a href="http://192.168.0.232/kids?profile=tablet_kendra_time">Kendra - Tablet - TIME</a><br><br><br>
<a href="http://192.168.0.232/kids?profile=tablet_kendra_free">Kendra - Tablet - FREE</a><br><br><br>
Debug:<br><br>
%s
</body></html>
""" % (abc)
Code: Alles auswählen
# -*- coding: utf-8 -*-
##############################################################################
# 2013 E2OpenPlugins #
# #
# This file is open source software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License version 2 as #
# published by the Free Software Foundation. #
# #
##############################################################################
from twisted.web import static, resource, http, server
import time
import socket
import base64
class JKController(resource.Resource):
global push
def __init__(self, session, path = ""):
resource.Resource.__init__(self)
self.session = session
def push(key):
src = '192.168.0.232' # ip of remote
mac = '00-1D-EC-06-C2-C5' # mac of remote
remote = 'python remote' # remote name
dst = '192.168.0.155' # ip of tv
app = 'python' # iphone..iapp.samsung
tv = 'UE40C6700' # iphone.LE32C650.iapp.samsung
new = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
new.connect((dst, 55000))
msg = chr(0x64) + chr(0x00) +\
chr(len(base64.b64encode(src))) + chr(0x00) + base64.b64encode(src) +\
chr(len(base64.b64encode(mac))) + chr(0x00) + base64.b64encode(mac) +\
chr(len(base64.b64encode(remote))) + chr(0x00) + base64.b64encode(remote)
pkt = chr(0x00) +\
chr(len(app)) + chr(0x00) + app +\
chr(len(msg)) + chr(0x00) + msg
new.send(pkt)
msg = chr(0x00) + chr(0x00) + chr(0x00) +\
chr(len(base64.b64encode(key))) + chr(0x00) + base64.b64encode(key)
pkt = chr(0x00) +\
chr(len(tv)) + chr(0x00) + tv +\
chr(len(msg)) + chr(0x00) + msg
new.send(pkt)
new.close()
time.sleep(0.1)
def render(self, request):
if "key" in request.args.keys():
key = request.args["key"][0]
if key == "001":
push("KEY_TV")
push("KEY_1")
push("KEY_ENTER")
if key == "002":
push("KEY_TV")
push("KEY_2")
push("KEY_ENTER")
if key == "003":
push("KEY_TV")
push("KEY_3")
push("KEY_ENTER")
if key == "004":
push("KEY_TV")
push("KEY_4")
push("KEY_ENTER")
if key == "005":
push("KEY_TV")
push("KEY_5")
push("KEY_ENTER")
if key == "006":
push("KEY_TV")
push("KEY_6")
push("KEY_ENTER")
if key == "007":
push("KEY_TV")
push("KEY_7")
push("KEY_ENTER")
if key == "008":
push("KEY_TV")
push("KEY_8")
push("KEY_ENTER")
if key == "009":
push("KEY_TV")
push("KEY_9")
push("KEY_ENTER")
if key == "010":
push("KEY_TV")
push("KEY_1")
push("KEY_0")
push("KEY_ENTER")
if key == "011":
push("KEY_TV")
push("KEY_1")
push("KEY_1")
push("KEY_ENTER")
if key == "016":
push("KEY_TV")
push("KEY_1")
push("KEY_6")
push("KEY_ENTER")
if key == "017":
push("KEY_TV")
push("KEY_1")
push("KEY_7")
push("KEY_ENTER")
if key == "018":
push("KEY_TV")
push("KEY_1")
push("KEY_8")
push("KEY_ENTER")
if key == "019":
push("KEY_TV")
push("KEY_1")
push("KEY_9")
push("KEY_ENTER")
if key == "020":
push("KEY_TV")
push("KEY_2")
push("KEY_0")
push("KEY_ENTER")
if key == "021":
push("KEY_TV")
push("KEY_2")
push("KEY_1")
push("KEY_ENTER")
if key == "023":
push("KEY_TV")
push("KEY_2")
push("KEY_3")
push("KEY_ENTER")
if key == "TV":
push("KEY_TV")
if key == "OFF":
push("KEY_POWEROFF")
if key == "AV1":
push("KEY_AV1")
if key == "HDMI":
push("KEY_HDMI")
if key == "MUTE":
push("KEY_MUTE")
if key == "DVI1":
push("KEY_AV1")
push("KEY_HDMI")
if key == "DVI2":
push("KEY_AV1")
push("KEY_HDMI")
time.sleep(1)
push("KEY_HDMI")
if key == "DVI3":
push("KEY_AV1")
push("KEY_HDMI")
time.sleep(1)
push("KEY_HDMI")
time.sleep(1)
push("KEY_HDMI")
if key == "DVI4":
push("KEY_AV1")
push("KEY_HDMI")
time.sleep(1)
push("KEY_HDMI")
time.sleep(1)
push("KEY_HDMI")
time.sleep(1)
push("KEY_HDMI")
if key == "VOLUP":
push("KEY_VOLUP")
if key == "VOLDOWN":
push("KEY_VOLDOWN")
if key == "test":
push("KEY_EXT1")
request.setResponseCode(http.OK)
request.setHeader('Content-type', 'text/html')
request.setHeader('charset', 'UTF-8')
return """<b>TV Fernbedienung</b><br><br>
<style>a {font-weight: bold; font-size: 40px}, td {height: 150px}</style>
<table border="1" width="100%" height="100px">
<colgroup>
<col width="1*">
<col width="1*">
<col width="1*">
</colgroup>
<tr>
<td height="130px"><a href="http://192.168.0.232/jk?key=001">Sat 1</a></td>
<td><a href="http://192.168.0.232/jk?key=002">RTL</a></td>
<td><a href="http://192.168.0.232/jk?key=003">Pro 7</a></td>
</tr>
<tr>
<td height="130px"><a href="http://192.168.0.232/jk?key=004">VOX</a></td>
<td><a href="http://192.168.0.232/jk?key=005">Kablen 1</a></td>
<td><a href="http://192.168.0.232/jk?key=006">RTL 2</a></td>
</tr>
<tr>
<td height="130px"><a href="http://192.168.0.232/jk?key=007">Super RTL</a></td>
<td><a href="http://192.168.0.232/jk?key=008">SIXX</a></td>
<td><a href="http://192.168.0.232/jk?key=009">ARD</a></td>
</tr>
<tr>
<td height="130px"><a href="http://192.168.0.232/jk?key=010">ZDF</a></td>
<td><a href="http://192.168.0.232/jk?key=011">KIKA</a></td>
<td><a href="http://192.168.0.232/jk?key=016">DMAX</a></td>
</tr>
<tr>
<td height="130px"><a href="http://192.168.0.232/jk?key=017">3 Sat</a></td>
<td><a href="http://192.168.0.232/jk?key=018">NDR</a></td>
<td><a href="http://192.168.0.232/jk?key=019">WDR</a></td>
</tr>
<tr>
<td height="130px"><a href="http://192.168.0.232/jk?key=020">HR</a></td>
<td><a href="http://192.168.0.232/jk?key=021">MDR</a></td>
<td><a href="http://192.168.0.232/jk?key=023">BR Alpha</a></td>
</tr>
<tr>
<td height="130px"><a href="http://192.168.0.232/jk?key=VOLUP">VOL +</a></td>
<td><a href="http://192.168.0.232/jk?key=VOLDOWN">VOL -</a></td>
<td><a href="http://192.168.0.232/jk?key=MUTE">MUTE</a></td>
</tr>
<tr>
<td height="130px"><a href="http://192.168.0.232/jk?key=DVI1">Recorder</a></td>
<td><a href="http://192.168.0.232/jk?key=DVI2">Apple TV</a></td>
<td><a href="http://192.168.0.232/jk?key=DVI3">Fire TV</a></td>
</tr>
<tr>
<td height="130px"><a href="http://192.168.0.232/jk?key=DVI4">Blue Ray</a></td>
<td><a href="http://192.168.0.232/jk?key=test">XXX</a></td>
<td><a href="http://192.168.0.232/jk?key=XXX">XXX</a></td>
</tr>
<tr>
<td height="130px"><a href="http://192.168.0.232/jk?key=TV">TV</a></td>
<td><a href="http://192.168.0.232/jk?key=OFF">OFF</a></td>
<td><a href="http://192.168.0.232/jk?key=HDMI">HDMI</a></td>
</tr>
</table>
</body>
"""
Zuletzt geändert von Anonymous am Samstag 12. August 2017, 23:09, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
@kluesi: Im ersten Programm werden `base64`, `socket`, `time`, `static` und `server` importiert, aber nicht verwendet.
Der Klassenname `kidsController` hält sich nicht an die Namenskonventionen und sollte `KidsController` heissen. Siehe den Style Guide for Python Code.
``global`` hat in sauberen Programmen nichts zu suchen. Insbesondere wenn man sowieso schon objektorientiert programmiert gibt es dafür keine Ausrede mehr.
`ergebnis` wird zudem auch überhaupt nicht verwendet.
Und das man ``global`` auf Klassenebene verwendet um eine Funktion ausserhalb der Klasse zu definieren habe ich noch nie gesehen. Das ist extrem verwirrend und undurchsichtig.
Importe gehören an den Anfang eines Moduls, damit man dort schnell/leicht erkennen kann wovon ein Modul abhängig ist. Zu den importierten aber nicht verwendeten Modulen kommen dann noch mal `getpass` und `sys` dazu.
Für das schliessen der Telnetverbindung böte sich die ``with``-Anweisung im Zusammenhang mit `contextlib.closing()` an.
Die Kommentare in `setProfile` bieten keinen Mehrwert, weil sie nur das wiederholen was im Vergleich beim ``if`` bereits steht.
Für die ``if``\s nach dem ersten hätte man besser ``elif`` verwendet. Beziehungsweise ist da sowieso eine Menge Wiederholung drin. Ein Wörterbuch das die Profilnamen auf die veränderlichen Teile die per Telnet übermittelt werden, abbildet, wäre weniger kopieren und einfügen gewesen.
Auch der HTML-Code besteht aus viel kopieren und einfügen und auch diese Werte hätte man mit in die Datenstruktur aufnehmen können. Denn die Profilnamen wiederholen sich auch dort noch mal.
Im zweiten Plugin ist auch wieder diese echt schräge Verwendung von ``global`` und viel kopieren und eingfügen das man mit Code hätte lösen können/sollen.
Der Klassenname `kidsController` hält sich nicht an die Namenskonventionen und sollte `KidsController` heissen. Siehe den Style Guide for Python Code.
``global`` hat in sauberen Programmen nichts zu suchen. Insbesondere wenn man sowieso schon objektorientiert programmiert gibt es dafür keine Ausrede mehr.
`ergebnis` wird zudem auch überhaupt nicht verwendet.
Und das man ``global`` auf Klassenebene verwendet um eine Funktion ausserhalb der Klasse zu definieren habe ich noch nie gesehen. Das ist extrem verwirrend und undurchsichtig.
Importe gehören an den Anfang eines Moduls, damit man dort schnell/leicht erkennen kann wovon ein Modul abhängig ist. Zu den importierten aber nicht verwendeten Modulen kommen dann noch mal `getpass` und `sys` dazu.
Für das schliessen der Telnetverbindung böte sich die ``with``-Anweisung im Zusammenhang mit `contextlib.closing()` an.
Die Kommentare in `setProfile` bieten keinen Mehrwert, weil sie nur das wiederholen was im Vergleich beim ``if`` bereits steht.
Für die ``if``\s nach dem ersten hätte man besser ``elif`` verwendet. Beziehungsweise ist da sowieso eine Menge Wiederholung drin. Ein Wörterbuch das die Profilnamen auf die veränderlichen Teile die per Telnet übermittelt werden, abbildet, wäre weniger kopieren und einfügen gewesen.
Auch der HTML-Code besteht aus viel kopieren und einfügen und auch diese Werte hätte man mit in die Datenstruktur aufnehmen können. Denn die Profilnamen wiederholen sich auch dort noch mal.
Im zweiten Plugin ist auch wieder diese echt schräge Verwendung von ``global`` und viel kopieren und eingfügen das man mit Code hätte lösen können/sollen.