Ankündigung

Einklappen
Keine Ankündigung bisher.

Plugin Denon ohne Telnet Interface / mit UPNP Support

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    #31
    Hallo Mirko,

    schaue ich mir nochmal an. Warum ist das so gemacht. Bei kleinen Zykluszeiten Empfehlung Marcus, das in Run mit der Schleife zu machen, da sonst bei einem Problem in den zyklischen Tasks die worker thread vollllaufen und dann das System hängt. Bei größeren Zykluszeiten per Scheduler und dann aber in das init mit rein (da war es auch einmal). Ich arbeite im Moment mit 1 Sekunde (ist sicherlich eher der Lasttest).

    Im nächsten release gehen ich auf Min Zykluszeit 5 Sekunden und dann auch in die Init Routine. Dann ist time.sleep weg :-)

    Den Befehlssatz für die Quellen ist
    Code:
     [FONT=Monaco][SIZE=11px]                {{ basic.button(id~'input_internet',         gad_input,'','pics/denon/internetradio.png'    ,'SIIRP') }}[/SIZE][/FONT]
      [FONT=Monaco][SIZE=11px]                {{ basic.button(id~'input_blueray',         gad_input,'','pics/denon/blueray.png'        ,'SIBD') }}[/SIZE][/FONT]
      [FONT=Monaco][SIZE=11px]                {{ basic.button(id~'input_medienserver',     gad_input,'','pics/denon/mediaserver.png'    ,'SISERVER') }}[/SIZE][/FONT]
      [FONT=Monaco][SIZE=11px]                {{ basic.button(id~'input_sattv',             gad_input,'','pics/denon/sattv.png'            ,'SISAT/CBL') }}[/SIZE][/FONT]
      [FONT=Monaco][SIZE=11px]                {{ basic.button(id~'input_usb',             gad_input,'','pics/denon/usb.png'            ,'SIUSB') }}[/SIZE][/FONT]
      [FONT=Monaco][SIZE=11px]                {{ basic.dual(id~'power',                     gad_power, icon1~'control_standby.png', icon0~'control_standby.png') }}[/SIZE][/FONT]
      [FONT=Monaco][SIZE=11px]                {{ basic.dual(id~'mute',                     gad_mute, icon1~'audio_volume_mute.png', icon0~'audio_volume_mute.png', 1, 0) }}[/SIZE][/FONT]
    siehe auch widget_denn.html

    Für die App direct Befehle ist richtig z.B.:
    Code:
     [FONT=Monaco][SIZE=11px]'Z2PSTRE <x>'[/SIZE][/FONT]
    , wobei der Befehl im String steht. Fall der Befehl einen Parameter erwartet, steht dann im String <x>, das durch den Wert des zugehörigen Items selbst ersetzt wird.

    Michel

    Kommentar


      #32
      Also das mit dem Input wird sich dann echt überschnitten haben.

      Ich hab Zyklus auf 60 Sekunden ... nachts ist der X1000 aus sonst dann ist mein Log voll wenn ich alle 5 Sekunde mitgeteilt bekomme dass er nicht erreichbar ist .
      Umgezogen? Ja! ... Fertig? Nein!
      Baustelle 2.0 !

      Kommentar


        #33
        ...eigentlich sollte "timed out" und "Host is down" abgefangen sein (siehe _request()) und kein log geschrieben werden. Dafür gibt es anstelle (sofern definiert) einen Error Eintrag in ein Status Item....
        Evt. meldet der X1000 etwas gleich anderes zurück. Kannst Du einen den Log Eintrag mal posten ?

        Kommentar


          #34
          Ich hab nur morgens als alles schlief mit ner Tasse Kaffe durch den Code gewühlt.

          Seh ich mir die Woche nochmal an.
          Umgezogen? Ja! ... Fertig? Nein!
          Baustelle 2.0 !

          Kommentar


            #35
            Also meine Fehlermeldung ist folgende:
            Code:
            2015-03-09 01:28:34 ERROR    denon        DENON: _request: problem in http.client exception : [Errno 113] Keine Route zum Zielrechner
            Wird also im Code nicht abgefangen.
            Momentan scheitere ich aber an der Aktualisierung bzw. läuft die Zonenabfrage ins Leere. Ich hab mir dazu eine Debug-Ausgabe gemacht:

            Code:
                    # merker, welche zone konfiguriert wurde. ich möchte keine abfragen, die nicht konfiguriert ist
                    self._configuredZones = {}
                    logger.warning('DENON: _configuredZones: {0}'.format(self._configuredZones))
            Damit sollte ist klar das _configuredZones leer ist:

            Code:
            2015-03-09 19:46:45,721 DEBUG    Main         Plugin: denon -- plugin.py:__init__:43
            2015-03-09 19:46:45,772 WARNING  Main         DENON: _configuredZones: {} -- __init__.py:__init__:56
            Jetzt weiß ich auch warum:
            Du holst Du Zonen aus dem Parser, der läuft aber zwischen init und run. Deshalb macht es u.U. Sinn den Scheduler auch da hin zu setzen (nach run).
            Hier funktioniert das getestet jetzt so:
            Code:
            class Denon():
            
                # Initialize connection to receiver
                def __init__(self, smarthome, denon_ip, denon_port = '80', denon_upnp_port = '8080', cycle = 5):
                    
            #        pydevd.settrace('192.168.2.57')
                    self._denonIp = denon_ip
                    self._denonPort = denon_port
                    self._denonUpnpPort = denon_upnp_port
                    self._sh = smarthome
                    self._cycle = int(cycle)
                    # lower limit cycle 
                    if self._cycle < 5:
                        self._cycle = 5
                    # variablen zur steuerung des plugins
                    # hier werden alle bekannte items für lampen eingetragen
                    self._sendKeys = {'MasterVolume', 'Power', 'Mute', 'InputFuncSelect', 'SurrMode', 'SetAudioURI'}
                    self._listenKeys = {'MasterVolume', 'Power', 'Mute', 'InputFuncSelect', 'SurrMode', 'szLine',
                                        'DeviceZones', 'MacAddress', 'ModelName'} 
                    # die Zones werden in der Device übersicht mit 0 = main und 1 = zone2 übertragen
                    self._zoneName = {'0' : 'Status', '1' : 'MAIN ZONE', '2': 'ZONE2'}
                    self._zoneXMLCommandURI = {'0' :'/goform/formNetAudio_StatusXml.xml', '1' : '/goform/formMainZone_MainZoneXmlStatus.xml', '2': '/goform/formZone2_Zone2XmlStatus.xml'}
                    self._XMLDeviceInfoURI = {'0': '/goform/Deviceinfo.xml'}
                    # hier werden alle bekannte items für den denon eingetragen
                    # items, die fürs senden konfiguriert sind 
                    self._sendItems = {}
                    # items, die fürs empfangen konfiguriert sind 
                    self._listenItems = {}
                    # merker, welche zone konfiguriert wurde. ich möchte keine abfragen, die nicht konfiguriert ist
                    self._configuredZones = {}
                    # lock, um mehrfache zugriffe auf request zu seriealisieren
                    self._requestLock = threading.Lock()
                    # die uri für denupnp command channel gilt für den x3000
                    # evt. muss hier über einen discovery mechanismus die richtig herausgefunden werden
                    # im moment wird die konfiguration statisch gebaut bzw. vorgegeben. in einem erweiterungsschritt
                    # könnte man die xml SOAP nachrichten per eTree zusammenbauen.
                    self._uriCommand = "/AVTransport/ctrl"
                    self._SetAVTransportURI = { 
                        'headers': {
                            'SOAPACTION': '"urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI"',
                            'CONTENT-TYPE' : 'text/xml; charset="utf-8"',
                            'USER-AGENT' :'smarthome/denon plugin v0.1' 
                                    },
                        'body': '<?xml version="1.0" encoding="utf-8"?>\r\n'
                            '<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">\r\n'
                                '<s:Body>'
                                    '<u:SetAVTransportURI xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">\r\n'
                                        '<InstanceID>0</InstanceID>\r\n'
                                        '<CurrentURI>{0}</CurrentURI>\r\n'
                                        '<CurrentURIMetaData>' 
                                        '</CurrentURIMetaData>\r\n'
                                    '</u:SetAVTransportURI>\r\n'
                                '</s:Body>\r\n'
                            '</s:Envelope>\r\n' 
                        }
                    self._Play = {
                        'headers': {
                            'SOAPACTION': '"urn:schemas-upnp-org:service:AVTransport:1#Play"',
                            'CONTENT-TYPE' : 'text/xml; charset="utf-8"',
                            'USER-AGENT' :'smarthome/denon plugin v0.1' 
                            },
                        'body': '<?xml version="1.0" encoding="utf-8"?>\r\n'
                            '<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">\r\n'
                                '<s:Body>'
                                    '<u:Play xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">\r\n'
                                        '<InstanceID>0</InstanceID>\r\n'
                                        '<Speed>1</Speed>\r\n'
                                    '</u:Play>\r\n'
                                '</s:Body>\r\n'
                            '</s:Envelope>\r\n' 
                    } 
                    
                def run(self):
                    self.alive = True
                    # einmalig zum start die Device info abholen
                    self._get_deviceinfo()
                    # jetzt noch die zyklischen aufgaben
                    # ich hole regelmässig im polling den wert der zonen
                    # allerdings nur für die konfigurierten zonen
                    for zone in self._configuredZones:
                        self._sh.scheduler.add('DENON', self._update_status(zone), prio=5, cycle=self._cycle, offset=2)
            Grüße


            Umgezogen? Ja! ... Fertig? Nein!
            Baustelle 2.0 !

            Kommentar


              #36
              Zu früh gefreut:
              Code:
               2015-03-09 20:29:57,453 ERROR    Denon        Method Denon exception: 'NoneType' object is not callable -- scheduler.py:_task:362
                Traceback (most recent call last):
                  File "/usr/local/smarthome/lib/scheduler.py", line 358, in _task
                    obj()
                TypeError: 'NoneType' object is not callable
              Jetzt bin ich mir nicht sicher ob ich mich recht erinnere. Soweit ich weiß kann/konnte man dem Scheduler keine Variablen (hier zone) für die aufzurufende Routine mitgeben. Kannst Du das mal verifizieren oder erklären warum bei Dir überhaupt was eingetragen wird obwohl die Anzahl der Zonen noch nicht bekannt ist?

              Code:
              self._sh.scheduler.add('Denon', self._update_status[B](zone)[/B], prio=5, cycle=self._cycle, offset=2)

              Der Scheduler meckert nicht mehr (dafür natürlich das Plugin wenn man folgendes macht:
              Code:
              self._sh.scheduler.add('Denon', self._update_status, prio=5, cycle=self._cycle, offset=2)
              Also scheint meine Erinnerung mich nicht zu trügen.
              Umgezogen? Ja! ... Fertig? Nein!
              Baustelle 2.0 !

              Kommentar


                #37
                So langsam wirds von mir hier zum Spam

                Also folgendes kann man da machen:

                Den Scheduler in dir run-Methode:
                Code:
                    def run(self):
                        self.alive = True
                        # einmalig zum start die Device info abholen
                        self._get_deviceinfo()
                        # jetzt noch die zyklischen aufgaben
                        # ich hole regelmässig im polling den wert der zonen
                        # allerdings nur für die konfigurierten zonen
                        self._sh.scheduler.add('Denon', self._update_status, prio=5, cycle=self._cycle, offset=2)
                Das iterieren über die Zonen macht man dann direkt im _update_status:
                Code:
                    def _update_status(self):
                        for denonZone in self._configuredZones:    
                            # Poll XML status
                            # ToDo müssen alle themen wirklich so abgearbeitet werden, oder kann ich auf ein subset referezieren bei der Abarbeitung des XML
                            # status abholen
                            self._requestLock.acquire()
                            responseEtree = self._request(self._denonIp, self._denonPort, 'GET', self._zoneXMLCommandURI[denonZone])
                            self._requestLock.release()
                            # im falle eines fehlers wird None zurückgeliefert
                            if responseEtree is not None:
                                # durchinterieren über alle einträge für das listen
                                # es ist nur die erste ebene !
                                for node in responseEtree:
                Das geht natürlich nur wenn Du die _update_status nicht noch gezielt für was anderes einsetzen willst.

                Nun nerv ich aber für heute nicht weiter

                Grüße Mirko
                Umgezogen? Ja! ... Fertig? Nein!
                Baustelle 2.0 !

                Kommentar


                  #38
                  Hallo Mirko,

                  keine Angst, da muß viel passieren, bis ich genervt bin. Gerne arbeite ich an einem Thema, wo ich einen Sparring habe, dann geht's meistens besser. Am Code kann ich erst die nächsten Tage was machen. Ich würde nur gerne mal sortieren:
                  - In einem Plugin wird init() und run() erst dann aufgerufen, wenn alle items geparsed sind. Damit ist die Anzahl der Zonen bekannt. wenn es nicht so ist, habe ich ich nicht einen Fehler irgendwo.
                  - Der scheduler verträgt keine Parameter. Das hätte mir auch auffallen müssen, da ja nur die Methode selbst übergeben wird.
                  - Normalerweise wird der scheduler in init() aufgemacht. Das gehört dorthin, weil init() genau! einmal aufgerufen wird. Bei run() sollte das zwar auch so sein, nach Aussage Marcus kann es aber auch mal mehr sein (dann hätten wir in Grenzfällen mehrfache scheduler Einträge)
                  - Aus meiner Sicht für einen Status braucht man eine Zykluszeit im kleinen Sekundenbereich, sonst bekommt man Änderungen schlicht nicht mit.
                  - Zyklen mit kleiner Zykluszeit nach Empfehlung Marcus in einer Schleife in run(), nicht mit scheduler, weil sonst ...(aber das hatten wir schon)

                  ->Damit aus meiner Sicht das Ziel, wieder zurück zum Anfang: run() mit schleife
                  Dass Du auf 60 Sekunden bist, liegt am vollen Log. Da habe ich Fehlerbedingungen noch nicht abgefangen. Das IP Geräte komplett ausgeschaltet werden, die im Polling drin sind passiert häufiger, die Situation haben ich auch bei anderen geschriebenen Plugins. Das muß ich generell lösen. Hier schaue ich mir auch mal die lib von Marcus an (lib.www.Client) an. Die kann das auch noch nicht, aber das muss einmal gelöst werden.

                  Ja viel geschrieben, noch nicht angefangen.

                  Michel

                  Kommentar


                    #39
                    Aufgefallen ist mir die Problematik ja lediglich beim debuggen. Da habe ich gesehen das hs.py einfach nicht sauber runterfährt weil es in einem sleep vom Denon-Plugin hängt. Das war der eigentlich Umstand den ich abschalten wollte .

                    Da wir die Zonen eh nicht übergeben hast Du natürlich recht das man dann wieder in init wechseln kann (mit scheduler) oder eben ein sleep in run.

                    Reihenfolge ist meiner Meinung nach aber so: init -> parse -> run. Müsste ich aber nochmal nachsehen.

                    Da hatte ich mich gestern Abend dann selbst drin verzettelt. Da cycle konfigurierbar ist, würde ich trotzdem zum scheduler tendieren, das ist aber eher eine persönliche Vorliebe und letztlich Dein Plugin. Das testen fällt mir Abends mit der Familie vorm TV natürlich deutlich schwerer .

                    Umgezogen? Ja! ... Fertig? Nein!
                    Baustelle 2.0 !

                    Kommentar


                      #40
                      Ja das mit der Wartezeit ist schlecht, nicht nur beim Debuggen. Wegen dem scheduler: ich hatte bei meinen anderen Plugins mal nachgesehen, dort bin ich auch beim scheduler gelandet. Damit ich im Kopf nur eine Lösung mir merken muß, tendiere ich jetzt auch eher dorthin. Das mit dem Test Abends habe ich das gleiche Problem. Kommt irgendwie nicht gut !

                      Kommentar


                        #41
                        Guten Abend,

                        hat vielleicht einer mal seine items.conf zum Vergleich?
                        Ich schaff es irgendwie nicht einen 1100w ein/auszuschalten..

                        meine items.conf:

                        (ich will nur per KNX Taster ein/ausschalten)
                        [denon]
                        denon_zone = 1
                        [[power]]
                        type = bool
                        denon_send = Power
                        denon_listen = Power

                        und zum ausschalten in eine funtionierende Logik die Zeile
                        sh.denon.power(0) eingefügt.

                        danke, Sven
                        Zuletzt geändert von svenmueller; 21.03.2015, 20:56.

                        Kommentar


                          #42
                          Hallo Sven,

                          anbei meine item für den x3000:
                          Code:
                           [FONT=Monaco][SIZE=11px][[U]mm[/U]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]    [[[U]denon[/U]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px] [/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]        [[[status]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            denon_zone = 0[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            # device [U]infos[/U] -> received once per start[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            [[[[ModelName]]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                type = [U]str[/U][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_listen = ModelName[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            [[[[DeviceZones]]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                type = [U]str[/U][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_listen = DeviceZones[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            [[[[MacAddress]]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                type = [U]str[/U][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_listen = MacAddress[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            # [U]staus[/U] objects received cyclic[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            [[[[nowPlaying]]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                type = [U]str[/U][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_listen = szLine[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            [[[[[U]errorstatus[/U]]]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                type = [U]str[/U][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_listen = [U]errorstatus[/U][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px] [/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]        [[[main]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            denon_zone = 1[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            [[[[Power]]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                type = [U]bool[/U][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_send = Power[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_listen = Power[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            [[[[MasterVolume]]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                type = [U]num[/U][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_send = MasterVolume[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_listen = MasterVolume[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            [[[[Mute]]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                type = [U]bool[/U][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_send = Mute[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_listen = Mute[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            [[[[Input]]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                type = [U]str[/U][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_command = '[U]<x>[/U]'[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_listen = InputFuncSelect[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            [[[[SurrMode]]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                type = [U]str[/U][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_command = '[U]<x>[/U]'[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_listen = SurrMode[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            [[[[[U]seturi[/U]]]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                type = [U]str[/U][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_send = SetAudioURI[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                enforce_updates = true [/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            [[[[Treble]]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                type = [U]num[/U][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_command = 'Z2PSTRE [U]<x>[/U]'[/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]            [[[[Bass]]]][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                type = [U]num[/U][/SIZE][/FONT]
                            [FONT=Monaco][SIZE=11px]                denon_command = 'PSBAS [U]<x>[/U]'[/SIZE][/FONT]
                          Du kannst auch einmal probieren, ob Du den Receiver die Befehle

                          Code:
                           
                           [FONT=inherit]Main Zone[/FONT] http://<AV IP-Adresse>/goform/formiPhoneAppPower.xml?1+PowerOn http://<AV IP-Adresse>/goform/formiPhoneAppPower.xml?1+PowerStandby [FONT=inherit]Zone 2[/FONT] http://<AV IP-Adresse>/goform/formiPhoneAppPower.xml?2+PowerOn http://<AV IP-Adresse>/goform/formiPhoneAppPower.xml?2+PowerStandby
                          dirket steuern kannst.

                          Michel

                          Kommentar


                            #43
                            Alles klar, danke!
                            Mein Fehler: Ich hatte am Denon nicht eingeschaltet das er über LAN aus dem Standby kommen kann.
                            Jetzt geht es super!

                            Gruß, Sven

                            Kommentar


                              #44
                              Na Klasse, dass es funktioniert !

                              Kommentar


                                #45
                                Hallo,

                                das Plugin funktioniert mit Denon und Onkyo, oder? Ich bin nämlich gerade auf der Suche (https://knx-user-forum.de/forum/%C3%B...erst%C3%A4rker).
                                Yamaha Receiver sind mit SH.py nicht steuerbar, oder?

                                Gruß,
                                Hendrik

                                Kommentar

                                Lädt...
                                X