Welches Framework nutzt meine VU SOLO2 Sat Receiver Box?

Django, Flask, Bottle, WSGI, CGI…
Antworten
kluesi
User
Beiträge: 8
Registriert: Freitag 21. Juli 2017, 12:19

Freitag 21. Juli 2017, 12:36

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
kluesi
User
Beiträge: 8
Registriert: Freitag 21. Juli 2017, 12:19

Freitag 21. Juli 2017, 12:42

Eins noch. Die Python Version ist 2.7
lackschuh
User
Beiträge: 277
Registriert: Dienstag 8. Mai 2012, 13:40

Freitag 21. Juli 2017, 12:46

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...
kluesi
User
Beiträge: 8
Registriert: Freitag 21. Juli 2017, 12:19

Sonntag 6. August 2017, 12:57

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

Code: Alles auswählen

Return """
Hallo Welt
"""
ausgeben. Aber sobald ich hier mit html Code ankomme gibt es nur Fehler. Bei mir sieht das so aus :

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)
So funktioniert es. Aber wenn ich anstatt dem hier, dass folgende verwende :

Code: Alles auswählen

return """
<html><body>Hallo</body></html>
"""
Bekomme ich nur Fehlermeldungen. Die Fehlermeldung habe ich gerade nicht zur Hand.

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.
BlackJack

Sonntag 6. August 2017, 13:28

@kluesi: Die wäre aber wichtig. Am besten inklusive Traceback 1:1 kopiert.
kluesi
User
Beiträge: 8
Registriert: Freitag 21. Juli 2017, 12:19

Sonntag 6. August 2017, 14:11

Dachte ich mir schon. Da komme ich erst heute Abend u. Es ging um ein Problem mit dem String. Aber ich gucke heute abend nochmal.

Viele Grüße
kluesi
User
Beiträge: 8
Registriert: Freitag 21. Juli 2017, 12:19

Sonntag 6. August 2017, 17:51

So. Hab das File mal aufgeräumt. Jetzt gibt es keine Fehler mehr. Es wird einfach der html Code selbst als Text ausgegeben. Was muss ich machen wenn ich das als html Code interpretiert haben möchte?
BlackJack

Sonntag 6. August 2017, 18:33

@kluesi: Den richtigen Content-Type senden, damit der Browser weiss was er damit machen soll.
kluesi
User
Beiträge: 8
Registriert: Freitag 21. Juli 2017, 12:19

Sonntag 6. August 2017, 19:39

Verdammt! Ja, natürlich war es das. Danke an alle, vg kkuesi
kluesi
User
Beiträge: 8
Registriert: Freitag 21. Juli 2017, 12:19

Samstag 12. August 2017, 21:06

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:

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>
"""
Vielen Dank
Zuletzt geändert von Anonymous am Samstag 12. August 2017, 23:09, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
kluesi
User
Beiträge: 8
Registriert: Freitag 21. Juli 2017, 12:19

Sonntag 13. August 2017, 15:41

So. Ich glaub ich hab es selbst hinbekommen. Ich habe dort wo es möglich ist timeouts eingestellt und im html habe ich die Tags für <html> und <body> weg gelassen. Jetzt scheint es kein Problem mehr zu geben.

Viele Grüße
BlackJack

Sonntag 13. August 2017, 17:33

@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.
Antworten