Ankündigung

Einklappen
Keine Ankündigung bisher.

NETIO230B Plugin

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

    NETIO230B Plugin

    Hallo,

    zur Steuerung meines Aquariums nutze ich eine NETIO230B Netzwerksteckdose. Ich habe mich dafür mal an einem Plugin versucht. Die Steckdose hat 4 Ports, die einzeln konfiguriert werden können. Das Plugin liefert 0 (aus), 1 (an) oder -1 (unbekannt) zurück. Die Portnummern beginnen bei 0. Über set_port(port,state) kann ein Port gesetzt werden. Danke für eure Verbesserungsvorschläge.

    Viele Grüße
    Mark

    plugin.conf

    Code:
    [netio230b]                                                                                             
        class_name = NetIO230B                                                                              
        class_path = plugins.netio230b                                                                      
        address = 192.168.2.1                                                                              
        user = username                                                                                        
        password = password
    items.conf

    Code:
    [netio0]                                                                                            
        name = NetIO230B                                                                                    
        netio_port = 0                                                                                      
        type = num                                                                                          
        value = -1
    plugins/netio230b/__init__.py:

    Code:
    #!/usr/bin/env python
    
    import logging
    from urllib2 import Request, urlopen, URLError
    import re
    
    logger = logging.getLogger('netio230b')
    
    class NetIO230B():
    
        def __init__(self, smarthome, address, user, password):
            self._sh = smarthome
            self.cycle = 10
            self.ports = dict()
            self.timeout = 2
            self.address = address
            self.user = user
            self.password = password
    
        def run(self):
            self._sh.scheduler.add('NetIO230B', self.update_status, cycle=self.cycle)
            self.alive = True
    
        def stop(self):
            self.alive = False
    
        def parse_item(self, item):
            if 'netio_port' in item.conf:
                self.ports[item.conf['netio_port']] = item
            return None
    
        def update_status(self):
            req = Request('http://'+self.address+'/tgi/control.cgi?login=p:'+self.user+':'+self.password+'&p=l')
            try:
              response = urlopen(req, timeout = self.timeout)
            except URLError as e:
              if hasattr(e, 'reason'):
                logger.error("failed to reach server: %s", str(e.reason))
              elif hasattr(e, 'code'):
                logger.error("server could not fulfill the request: %s", str(e.code))
    
              for key in self.ports.keys():
                self.ports[key](-1)
              return
    
            else:
              # read html response of format '<html>1 0 1 0 </html>'
              html = response.read()
              r = re.compile('[^0^1]')
              cur_state = filter(None, r.split(html))
    
              # assign values to items
              for key in self.ports.keys():
                try:
                  self.ports[key](cur_state[int(key)])
                except IndexError, e:
                  logger.error("no state for port: %s",str(e))
    
        def set_port(self,port,state):
            req=''
            if (state == 1) or (state == 0):
              for portnr in range(0, 4):
                if (portnr == port) and ((state == 0) or (state == 1)):
                  req += str(state)
                else:
                  req += 'u'
    
            req = Request('http://'+self.address+'/tgi/control.cgi?login=p:'+self.user+':'+self.password+'&p='+req)
            try:
              response = urlopen(req, timeout = self.timeout)
            except URLError as e:
              if hasattr(e, 'reason'):
                logger.error("failed to reach server: %s", str(e.reason))
              elif hasattr(e, 'code'):
                logger.error("server could not fulfill the request: %s", str(e.code))
            else:
              html = response.read()

    #2
    Hallo Mark,

    was soll ich sagen, erster Post und schon ein Plugin.

    Herzlich Willkommen hier im Forum, ich freue mich auf weitere Posts von Dir. (Auch wenn nicht immer ein Plugin drin ist)

    Ich bin leider zu müde um Dir qualifiziertes Feedback zu geben. Morgen habe ich Firmenlauf und komme daher erst am Donnerstag dazu.

    Bis bald

    Marcus

    Kommentar


      #3
      was soll ich sagen, erster Post und schon ein Plugin.
      Naja, ich habe ihn motiviert
      Derzeit zwischen Kistenauspacken und Garten anlegen.
      Baublog im Profil.

      Kommentar


        #4
        NETIO230B Plugin

        Hallo und herzlich Willkommen im Forum,

        kleine Manöverkritik: Macht das mit dem -1 wirklich sinn? Also gibt es den Status "unbekannt" im Normalfall überhaupt (wenn nicht gerade eine Exception auftritt, was nicht der Normalfall sein sollte)? Weil ein Item mit type=bool hätte den Vorteil, dass es leichter über KNX angesteuert werden kann. Nur mal so sls Denkanstoß.
        Mit freundlichen Grüßen
        Niko Will

        Logiken und Schnittstelle zu anderen Systemen: smarthome.py - Visualisierung: smartVISU
        - Gira TS3 - iPhone & iPad - Mobotix T24 - ekey - Denon 2313 - Russound C5 (RIO over TCP Plugin) -

        Kommentar


          #5
          Hi,

          danke an alle für die nette Begrüßung.

          @ 2ndsky

          Ja, mir wäre hier ein bool auch lieber. Für das Aquarium benötige ich aber einen Fehlerzustand, denn dann sollte ich mal nach dem Becken schauen. Man könnte hier eventuell ein zweites Item einführen, welches nur den Fehler anzeigt. Bin da für Ideen offen.

          Gruß
          Mark

          Kommentar


            #6
            Hallo Mark,

            das mit dem zweiten Item wäre eleganter und mehr KNX like... würde ich daher bevorzugen. Was bedeutet der Fehlerfall bei der Steckdosenleiste? Heißt das nur, dass die Kommunikation nicht funktioniert hat? Weil dann könntest du auch eine Art Sammelstörung machen.

            Und noch ein Verbesserungsvorschlag. Da es ja durchaus vorkommen kann, dass man mehr als nur eine solche Leiste im Haushalt hat, sollte man zusätzlich noch einen Identifier vergeben können. Ich habe das bei meinem SmartTV Plugin auch so gemacht. Dieser ist optional und wenn man nur eine hat kann der entfallen. Diese ID wird einmal in der plugin.conf und bei jedem Item angegeben. Hier mal ein Beispiel:

            Code:
            [netio230b_1]                                                                                             
                class_name = NetIO230B                                                                              
                class_path = plugins.netio230b                                                                      
                address = 192.168.2.101                                                                              
                user = username                                                                                        
                password = password
                id = 1
            
            [netio230b_2]                                                                                             
                class_name = NetIO230B                                                                              
                class_path = plugins.netio230b                                                                      
                address = 192.168.2.102                                                                              
                user = username
                id = 2                                                                                        
                password = password
            und die Items dann so:

            Code:
            [netio1_0]                                                                                            
                name = NetIO230B                                                                                    
                netio_port = 0
                netio_id = 1                                                                                      
                type = num                                                                                          
                value = -1
            
            [netio2_0]                                                                                            
                name = NetIO230B                                                                                    
                netio_port = 0
                netio_id = 2                                                                                      
                type = num                                                                                          
                value = -1
            Mit freundlichen Grüßen
            Niko Will

            Logiken und Schnittstelle zu anderen Systemen: smarthome.py - Visualisierung: smartVISU
            - Gira TS3 - iPhone & iPad - Mobotix T24 - ekey - Denon 2313 - Russound C5 (RIO over TCP Plugin) -

            Kommentar


              #7
              Hallo Mark,

              für den Anfang wirklich ein schönes kleines Plugin. Wie versprochen Feedback:
              • urllib2 hat leider ein Speicherleck. Schau dir mal sh.tools.fetch_url() an. Du könntest die Funktion wahrscheinlich auch direkt verwenden.
              • parse_item sollte am besten eine methode returnen. Dann kann man einfach durch ändern des Items die Steckdose schalten.
                Code:
                    def parse_item(self, item):
                        if 'netio_port' in item.conf:
                            self.ports[item.conf['netio_port']] = item
                            return self.update_item
                        else:
                            return None
                
                    def update_item(self, item, caller=None, source=None, dest=None):
                        self.set_port(item.conf['netio_port'], bool(item()))
              • Ich bin auch für eine separates Status-Attribute. Dadurch könnte man auch einfacher Meldungen über Mail oder Prowl verschicken.
              • Schau Dir doch mal das mpd-Plugin an, dort habe ich die Möglichkeit geschaffen mehrere Geräte mit nur einem Plugin-Objekt zu adressieren.
              • Für einen lauen Winterabend: Es wäre es auch interessant das Plugin auf Telnet umzustellen, vorausgesetzt Telnet bietet auch einen Monitormodus damit man nicht immer Pollen muss.
              • Misch bitte nicht die Einrücktiefen des Codes. z.T. sind es zwei z.T. vier Spaces => vier Spaces


              Danke für Deinen Beitrag, möge das Aquarium noch mehr Plugins benötigen ;-)

              Bis bald

              Marcus

              Kommentar


                #8
                Danke für eure Anregungen, ich werde sie einarbeiten und das Ergebnis hier posten.

                Gruß
                Mark

                Kommentar


                  #9
                  Hallo Mark,

                  Du musst das Ergebnis nicht hier posten.
                  Auch für Dich gilt: Du kannst Dir ja mal meinen neuen Plugin-Entwickler Guide ansehen und mir Deinen github-Account und Email-Adresse per PN zukommen lassen.

                  Bis bald

                  Marcus

                  Kommentar


                    #10
                    Hi Marcus,

                    bin gerade an der Umstellung. Gibt es einen Weg innerhalb des Plugins festzustellen, wer die Änderung des items bewirkt hat.Aktuell habe ich das Problem, dass das Plugin eine Änderung eines Ports feststellt und das item aktualisiert. Anschließend wird update_item aufgerufen, welches diesen Status im plugin erneut an die Steckdose sendet. Darauf würde ich gern verzichten, wenn die Änderung des Zustand durch das Plugin selbst vorgenommen wurde. caller ist immer mit "Logic" belegt, source und dest sind None. Alternativ kann ich mir sonst den Zustand auch im Plugin merken und nur bei einer Änderung reagieren.

                    Danke und Gruß
                    Mark

                    Kommentar


                      #11
                      NETIO230B Plugin

                      Hallo Mark,

                      Du musst den Caller bei der Änderung des Item mitgeben: item(Wert, caller='netio')
                      Dann kannst darauf prüfen.

                      Bis bald

                      Marcus

                      Kommentar

                      Lädt...
                      X