Ankündigung

Einklappen
Keine Ankündigung bisher.

Netatmo-Bausteine Hussong ohne Funktion?

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

    #16
    Bei mir funktioniert es auch nicht mehr.
    HS Neustart brachte keine Besserung. HS Version 4.11
    Angehängte Dateien

    Kommentar


      #17
      Haben wirklich nur wir 2 ein Problem?
      Im HS sagt er mir im Error Protokoll: Authentifizierung nicht erfolgreich: Fehler 400

      Kommentar


        #18
        Alle haben ab dem nächsten Neustart ein Problem, solange nur neue Tokens geholt werden läuft es noch.
        Netatmo hat "endlich" mal die Authentifizierung mittels Username/Passwort abgedreht.
        Wenn da eine eigene Dev App dahintersteckt, kann man sich einen Access Token auf dev.netatmo generieren und den nutzen.
        Im Code 'grant_type' = 'refresh_token'​ statt 'password' und 'refresh_token' statt der klassische Anmeldung an /oauth2/token

        Kommentar


          #19
          Danke für die Info.
          Das klärt zumindest, dass nicht ich das Problem bin.
          Leider bin ich ganz schlecht im Erstellen/Ändern von Homeserver Bausteinen

          Kommentar


            #20
            Zitat von mom Beitrag anzeigen
            Alle haben ab dem nächsten Neustart ein Problem, solange nur neue Tokens geholt werden läuft es noch.
            Netatmo hat "endlich" mal die Authentifizierung mittels Username/Passwort abgedreht.
            "nächster Neustart" - nächster Neustart der netatmo Basis oder des HS? Bei mir (HS4 mit FW4.10) läuft es aktuell noch, letzter Token-Refresh vor 4 min.!


            Möchte den Komfort meiner Installation nicht mehr missen!

            Kommentar


              #21
              Bei mir läuft es jetzt auch nicht mehr....
              Ich glaube aber mit einem Update sieht es schlecht aus.
              Der Entwickler hat sich glaube ich davon zurückgezogen nach einem Wechsel seines Arbeitgebers.... (Stand hier irgendwann mal im Forum).

              Muss ich mir leider eine Alternative suchen für den Regenmesser (War das einzige, was ich von der Netatmo wirklich im HS nutzte...)

              Kommentar


                #22
                Zitat von Hightech Beitrag anzeigen

                "nächster Neustart" - nächster Neustart der netatmo Basis oder des HS?

                HS Neustart.
                Hab Stephan Hussong eine Email geschrieben, hab aber noch nichts gehört.

                Kommentar


                  #23
                  Hhm, seit wann ist bei netatmo denn das update drin? Ich hab vor 3 oder 4 Tagen noch den HS gebooted und noch läuft alles?
                  Möchte den Komfort meiner Installation nicht mehr missen!

                  Kommentar


                    #24
                    Zitat von Hightech Beitrag anzeigen
                    "nächster Neustart" - nächster Neustart der netatmo Basis oder des HS? Bei mir (HS4 mit FW4.10) läuft es aktuell noch, letzter Token-Refresh vor 4 min.!
                    HS. Lass das also lieber mal laufen
                    Ich kenne den Baustein nicht, legt man sich dafür eine eigene Dev Applikation bei Netatmo an?

                    Zitat von Hightech Beitrag anzeigen
                    Hhm, seit wann ist bei netatmo denn das update drin? Ich hab vor 3 oder 4 Tagen noch den HS gebooted und noch läuft alles?
                    Seit ein paar Tagen.

                    Kommentar


                      #25
                      Gibt es vielleicht schon jemanden der versucht den Netatmo_OAUTH2 Baustein zu reparieren?

                      Kommentar


                        #26
                        Zitat von ad8755 Beitrag anzeigen
                        Gibt es vielleicht schon jemanden der versucht den Netatmo_OAUTH2 Baustein zu reparieren?
                        Was ist das denn für ein Baustein, in welcher Sprache ist er geschrieben und wo bekomme ich ihn her?

                        Kommentar


                          #27
                          Die Bausteine gibt es hier https://www.knxshop4u.ch/de/homeserv...rver-bausteine.

                          Kommentar


                            #28
                            Nein, da hast Du die Bausteine von Holger Eckert eckerho1 verlinkt, hier geht es um die Bausteine vom Stephan Hussong....

                            eckerho1: Denke, dass der ein oder andere demnächst dann auf Deine Bausteine umsteigen wird - kannst Du noch mal einen Screenshot von der Logik, wie man die Bausteine miteinander verbinden muss, posten? Hab über die SuFu keinen gefunden (obwohl ich bis 2014 zurückgegangen bin).
                            Zuletzt geändert von Hightech; 20.07.2023, 10:17.
                            Möchte den Komfort meiner Installation nicht mehr missen!

                            Kommentar


                              #29
                              Die Bausteine von Holger folgen dem gleichen Prinzip.
                              Beim ersten Mal geht es. Nach dem Neustart das gleiche Problem.
                              Alles probiert.

                              Der Authentifizierungsbaustein dürfte identisch sein.
                              Zuletzt geändert von Knochen; 20.07.2023, 10:37.

                              Kommentar


                                #30
                                Damit sollte es funktionieren, statt User/Pass ist nur noch der Refresh Token definiert, den man sich für seine eigene App unter dev.netatmo.com direkt im UI generieren kann.
                                Wie man das jetzt wieder in den Homeserver bekommt müsst ihr selbst wissen. Und was für eine scheußliche Programmiersprache ist das überhaupt? 🧐

                                Code:
                                class Netatmo_OAUTH213554(object):
                                    def __init__(self,pItem):
                                        from hs_queue import Queue
                                        pItem.NETATMO_OAUTH2 = self
                                        global threading
                                        import threading
                                
                                    def init_logik(self,pItem,EN):
                                        import types
                                
                                        pItem.client_id = EN[2]
                                        pItem.client_secret = EN[3]
                                        pItem.refresh_token = EN[4]
                                        pItem._scope= EN[5]
                                        pItem.abfrageAktiv = EN[6]
                                
                                        ## Wenn nicht eigene Client ID und Secret eingegeben, dann default verwenden, geht aber nicht fuer CAM
                                        if pItem.client_id == "":
                                            pItem.client_id = "5a08a3ffb26ddf727f8b5965"
                                        if pItem.client_secret == "":
                                            pItem.client_secret = "u5Kh7WXQswdsU79845uaIiGQ8hhqT27Ano"
                                
                                        pItem.id_token = ""
                                        pItem.scope = ""
                                        pItem.expiration = 999999999
                                        pItem.error = 0
                                
                                        ## dann den debug-Seiten Eintrag schreiben
                                        self.debug_write(pItem,"Herausgeber","<a target='_blank' href='http://www.ecmacom.ch'>ECMACOM GmbH</a>")
                                        self.debug_write(pItem,"Lizenz","Frei. ECMACOM lehnt jegliche Verantwortung ab. Einsatz auf eigenes Risoko")
                                        self.debug_write(pItem,"Abfrage", "{0}".format("angehalten" if EN[6] == 0 else "aktiv"))
                                        pItem._AUTH_REQ = "https://api.netatmo.com/oauth2/token"
                                        
                                        pItem.registered_device={} # Die registrierten devices. Verwendet um gezielte Updates senden zu knnen
                                        pItem.registered_device['data'] = {}
                                        pItem.registered_deviceName = {}
                                        pItem.known_devicetypes = ("Station","Home","HomeCoach")
                                
                                        ## Abfrage und loop starten
                                        self.loop_refreshToken(pItem)
                                
                                    ## Loop fr periodische Abfrage
                                    def loop_refreshToken(self,pItem):
                                        ## wenn aktiv
                                        if pItem.abfrageAktiv == 1:
                                            ## wenn noch kein Token oder fehler bei letzter Abrfage, neun Token holen
                                            if pItem.refresh_token == "" or pItem.error:
                                                self.getToken(pItem)
                                
                                        ## wenn error, dann stndlich neu versuchen
                                        if pItem.error:
                                            threading.Timer(3600, self.loop_refreshToken, args=(pItem,)).start()
                                        else:
                                            ## refreshToken nur machen wenn gettoken keinen error
                                            self.refreshToken(pItem)
                                            ## sonst alle expiration - 10 Min aufrufen
                                            threading.Timer(pItem.expiration - 600, self.loop_refreshToken, args=(pItem,)).start()
                                
                                
                                    ## Token vor Ablauf erneuern
                                    def refreshToken(self,pItem):
                                        import time
                                        postParams = {
                                                "grant_type" : "refresh_token",
                                                "refresh_token" : pItem.refresh_token,
                                                "client_id" : pItem.client_id,
                                                "client_secret" : pItem.client_secret
                                                }
                                        headers = {"Content-Type" : "application/x-www-form-urlencoded;charset=utf-8"}
                                        antwort, htmlrespcode = self.webRequest(pItem,"POST", pItem._AUTH_REQ, headers, postParams)
                                        ##wenn Anfrege erfolgreich
                                        if htmlrespcode == 200:
                                            
                                            pItem.id_token = antwort["access_token"]
                                            ## neuen Token an Geraetebausteine senden
                                            pItem.scope = antwort["scope"]
                                            pItem.scopestring = " ".join(map(str, pItem.scope))
                                            self.debug_write(pItem,"Scope, bestaetigt", pItem.scopestring)
                                            pItem.expiration = antwort["expire_in"]
                                            pItem.refresh_token = antwort["refresh_token"]
                                            self.debug_write(pItem,"Token refresh", time.strftime("%d.%m.%Y %H:%M:%S"))
                                            pItem.error = 0
                                            self.send_to_output(pItem,1,0)
                                            self.sendTokenToDevice(pItem)
                                
                                        else:
                                
                                            self.debug_write(pItem,"Token refresh", "Nicht erfolgreich " + str(htmlrespcode) + " . Entrge E1 bis E5 pruefen und HS neu starten")
                                            self.debug_write(pItem,"Abfrage", "angehalten")
                                            pItem.expiration = 999999999
                                            pItem.refresh_token = ""
                                            ## wenn nicht zum ersten Mal
                                            if pItem.error:
                                                pass
                                            else:
                                                pItem.error = 1
                                                self.send_to_output(pItem,1, 1)
                                                self.send_to_output(pItem,2, "Fehler beim Token Abfrage")
                                                self.log(pItem,"Fehler beim Token Abfrage",severity='error')
                                                self.send_to_output(pItem,1, 1)
                                            self.sendActivToDevice(pItem)
                                            
                                
                                    ## Erste Abfrage, Token generieren
                                    def getToken(self,pItem):
                                        postParams = {
                                                "grant_type" : "refresh_token",
                                                "client_id" : pItem.client_id,
                                                "client_secret" : pItem.client_secret,
                                                "refresh_token" : pItem.refresh_token,
                                                "scope" : pItem._scope
                                                }
                                        
                                        headers = {"Content-Type" : "application/x-www-form-urlencoded;charset=utf-8"}
                                        antwort, htmlrespcode = self.webRequest(pItem,"POST", pItem._AUTH_REQ, headers, postParams)
                                        ##webRequest(self, method, url, headers=None, params=None, timeout=10):
                                        if htmlrespcode == 200:
                                
                                            pItem.id_token = antwort["access_token"]
                                ##            pItem.scope = antwort["scope"]
                                ##            pItem.expiration = antwort["expire_in"]
                                            pItem.error = 0
                                            self.send_to_output(pItem,1, 0)
                                            pItem.refresh_token = antwort["refresh_token"]
                                            
                                        ## wenn Token Request fehler hatte
                                        else:
                                            self.send_to_output(pItem,2, "Token Anfrage nicht erfolgreich. Error: "+ str(htmlrespcode))
                                            self.log(pItem,"Token Anfrage nicht erfolgreich. Error: "+ str(htmlrespcode),severity='error')
                                            self.debug_write(pItem,"Abfrage", "angehalten")
                                            pItem.expiration = 999999999
                                            pItem.refresh_token = ""
                                            pItem.error = 1
                                            self.send_to_output(pItem,1, 1)
                                            self.sendActivToDevice(pItem)
                                
                                    def send_to_geraetebaustein(self,pItem, def_in_sub, logik_id, werte_zum_uebergeben):
                                        _dc = self._directconnect_parse(pItem, def_in_sub, logik_id)
                                        _getter = _dc.get("get") ## das ist die def im Gertebaustein. Die bekommt dann Daten vom return hier am Ende
                                        return _getter(werte_zum_uebergeben)
                                 
                                    def _directconnect_parse(self,pItem,def_in_sub,logik_id):
                                        _dc = {}
                                        try:
                                            _pItem = pItem.MC.LogikList.GatterList.get(int(logik_id))
                                            _dc["sourcelogik"] = _pItem.LogikItem
                                            _dc["source"]      = _pItem
                                            _dc["get"] = getattr(_pItem,def_in_sub,None)
                                        except ValueError:
                                            pItem.MC.Debug.setErr(sys.exc_info())
                                            ### LogikID pItem.ID keine int
                                            return {}
                                        return _dc
                                
                                
                                    def abfrage_start_stop(self,pItem,EN):
                                        pItem.abfrageAktiv = EN[7]
                                
                                        ## hier allen Bausteinen senden, dass Abfrage angehalten od. gestartet
                                        self.sendActivToDevice(pItem)
                                        if pItem.abfrageAktiv == 1:
                                            self.getToken(pItem)
                                            self.debug_write(pItem,"Abfrage", "aktiv")
                                        else:
                                            self.debug_write(pItem,"Abfrage", "angehalten")
                                
                                
                                    ## Abfrage des Code von API Webseite
                                    def webRequest(self,pItem,method, url, headers=None, params=None, timeout=10):
                                        import json
                                        import urllib
                                        import urllib2
                                        import ssl
                                
                                        ctx = ssl._create_unverified_context()
                                
                                        if params:
                                            if "json" in headers["Content-Type"]:
                                                params = json.dumps(params)
                                            else:
                                                params = urllib.urlencode(params)
                                        opener = urllib2.build_opener(urllib2.HTTPSHandler(context=ctx))
                                        req = urllib2.Request(url=url, data=params, headers=headers)
                                        req.get_method = lambda: method
                                        try:
                                            url = opener.open(req)
                                            ## wenn json
                                            if "application/json" in url.info().getheader('Content-Type'):
                                                return json.loads(url.read()),url.getcode()
                                            else:
                                                return"", 999
                                
                                        except urllib2.HTTPError as e:
                                            if hasattr(e,'code'):
                                                if e.code == 409:
                                                    self.send_to_output(pItem,2, "Ausfuehrungsbedingung(en) nicht erfuellt")
                                                    self.log(pItem,"Ausfuehrungsbedingung(en) nicht erfuellt",severity='error')
                                                else:
                                    ##                print e.code
                                    ##                print e.msg
                                    ##                print e.hdrs
                                    ##                print e.fp
                                                    self.send_to_output(pItem,2, "HTTP-Fehler bei der API-Abfrage method: " + method)
                                                    self.log(pItem,"HTTP-Fehler bei der API-Abfrage method: " + method,severity='error')
                                                return "", e.code
                                            else:
                                                self.send_to_output(pItem,2, "HTTP-Fehler bei der API-Abfrage")
                                                self.log(pItem,"HTTP-Fehler bei der API-Abfrage",severity='error')
                                            return "", 999
                                
                                        ## Often, URLError is raised because there is no network connection (no route to the specified server), or the specified server doesn?t exist. In this case, the exception raised will have a ?reason? attribute, which is a tuple containing an error code and a text error message
                                        except urllib2.URLError as e:
                                ##            print "URL ERROR"
                                ##            print e.reason
                                ##            print e.reason[0] ## code
                                ##            print e.reason[1] ## beschreibung
                                            self.send_to_output(pItem,2, "URL-Fehler bei der API-Abfrage method: " + method + " " + str(e.reason[0]) + " " + e.reason[1])
                                            self.log(pItem,"URL-Fehler bei der API-Abfrage method: " + method + " "  + str(e.reason[0]) + " " + e.reason[1],severity='error')
                                            return "", e.reason[0]
                                
                                        except:
                                            self.log(pItem,"Verbindungsfehler bei der API-Abfrage",severity='error')
                                            return "", 999
                                
                                    ## Profil Bausteine registrieren sich mit ihrer ID
                                    def registerProfil(self,pItem,EN):
                                        _data = EN[1]
                                        if _data.startswith("***DIRECTCONNECT***"):
                                            data = _data.split("#")
                                            bausteinID = data[1]
                                            logikID = data[2]
                                            name = data[4]
                                            deviceType= data[5]
                                            if pItem.error == 0 and pItem.abfrageAktiv == 1:
                                                activ = 1
                                            else:
                                                activ = 0
                                            werte_zum_uebergeben = (pItem.id_token, activ)
                                            
                                            ## nur wenn wir den Devicetype auch kennen
                                            if deviceType in pItem.known_devicetypes:
                                                if deviceType not in pItem.registered_device['data']:
                                                    pItem.registered_device['data'][deviceType] = {}
                                                if name not in pItem.registered_device['data'][deviceType]:
                                                    pItem.registered_device['data'][deviceType][name] = {}
                                                    pItem.registered_device['data'][deviceType][name] = {'BausiteinID':bausteinID,'logikID':logikID,'Hash':''}
                                
                                                    ## String mit registrieren Profil Namen zusammensetzen
                                                    if deviceType not in pItem.registered_deviceName:
                                                        pItem.registered_deviceName[deviceType] = {}
                                                    if len(pItem.registered_deviceName[deviceType]) >0:
                                                        pItem.registered_deviceName[deviceType] = str(pItem.registered_deviceName[deviceType]) + ", " + name
                                                    else:
                                                        pItem.registered_deviceName[deviceType] = name
                                                    self.debug_write(pItem,deviceType + " Clients angemeldet", pItem.registered_deviceName[deviceType])
                                
                                                    ## wenn wir schon einen token haben
                                                    if pItem.id_token != "":
                                                        ## wenn richtiger deviceType
                                                        ## Dann senden wir dem Client mal seinen Token wenn schon ein Token da ist
                                                        self.send_to_geraetebaustein(pItem,"directconnect_get_data", pItem.registered_device['data'][deviceType][name]['logikID'], werte_zum_uebergeben)
                                
                                    ## den hier mit 2 verschachtelten for i in anhandeln
                                    ## Token an Geraetebausteine senden
                                    def sendTokenToDevice(self,pItem):
                                        ## wenn token vorhanden
                                        if pItem.id_token != "":
                                            try: ## falls client noch nicht ganz angemeldet
                                                if pItem.error == 0 and pItem.abfrageAktiv == 1:
                                                    activ = 1
                                                else:
                                                    activ = 0
                                                werte_zum_uebergeben = (pItem.id_token, activ)
                                                for j in range(len(pItem.known_devicetypes)):
                                                    if pItem.known_devicetypes[j] in pItem.registered_device['data']:
                                                        for i in pItem.registered_device['data'][pItem.known_devicetypes[j]]:
                                                            self.send_to_geraetebaustein(pItem,"directconnect_get_data", pItem.registered_device['data'][pItem.known_devicetypes[j]][i]['logikID'], werte_zum_uebergeben)
                                            except:
                                                self.send_to_output(pItem,2, "Except in sendTokenToDevice")
                                                self.log(pItem,"Except in sendTokenToDevice",severity='error')
                                
                                    ## Activ an alle Geraetebausteine senden
                                    def sendActivToDevice(self,pItem):
                                        if pItem.error == 0 and pItem.abfrageAktiv == 1:
                                            activ = 1
                                        else:
                                            activ = 0
                                        for j in pItem.registered_device['data'] :
                                            for i in pItem.registered_device['data'][j]:
                                                self.send_to_geraetebaustein(pItem,"directconnect_abfrageaktiv", pItem.registered_device['data'][j][i]['logikID'], activ)
                                
                                    def debug_write(self,pItem,caption,msg):
                                        import hashlib
                                        _uniqueid = '13554_Netatmo_OAUTH2_1.55'
                                        _title = '13554_Netatmo_OAUTH2'
                                        _captionid = hashlib.md5(caption).hexdigest()
                                
                                        ## suche nach vorhandenem Eintrag in der Debugseite
                                        _grp = filter(lambda x: x[0]==_uniqueid,pItem.MC.Debug.Daten)
                                
                                        ## wenn noch kein Debugseiten Eintrag erstellen
                                        if not _grp:
                                            pItem.MC.Debug.addGruppe(
                                                [_uniqueid , _title],
                                                  [
                                                    ["0VERSIONINFO",      "Version", 1,'V1.55 - (2020-04-07 15:42)'],
                                                    [ _captionid ,   caption,    1, msg] ,
                                                  ]  
                                            )
                                        ## wenn schon vorhanden aktualisieren
                                        else:
                                            _grp_entry = _grp[0][2]
                                            _tok = filter(lambda x,y=_captionid: x[0]==y, _grp_entry)
                                            ## Unterschlssel vorhanden
                                            if _tok:
                                                _tok[0][1],_tok[0][3] =  caption, msg
                                            ## Unterschlssel erstellen
                                            else:
                                                _grp_entry.append( [ _captionid , caption,    1, msg ] )
                                
                                    def log(self,pItem,msg,severity='info'):
                                        import random
                                        import time
                                        from hashlib import md5 as _md5
                                        _msg_uid = _md5( "%s%s%s" % ( pItem.ID, random.random(), time.time() ) ).hexdigest()
                                        _msg = '<log><id>%s</id><facility>Netatmo_OAUTH2</facility><severity>%s</severity><message>%s</message></log>' % (_msg_uid,severity,msg)
                                        self.send_to_output(pItem,3,_msg)
                                
                                    def send_to_output(self,pItem,out,value):
                                        import time
                                        out -= 1 ## Intern starten die Ausgnge bei 0 und nicht bei 1
                                        if pItem.LogikItem.Ausgang[out][2] == 2 and pItem.OutWert[out] == value: ##sbc
                                            return
                                        ## Sendeintervall wird beachtet
                                        if pItem.SendIntervall == 0 or time.time() >= pItem.Ausgang[out][0]:
                                            ## Wert an allen iKOs an den Ausgngen setzen
                                            for iko in pItem.Ausgang[out][1]:
                                                pItem.MC.TagList.setWert(FLAG_EIB_LOGIK, iko, value)
                                            if value:
                                                for cmd in pItem.Ausgang[out][2]:
                                                    cmd.execBefehl()
                                            ## Direkte Verbindungen und Connectoren
                                            for con in pItem.Ausgang[out][3]:
                                                pItem.MC.LogikList.ConnectList.append(con + [value])
                                            ## Wenn Sendeintervall gesetzt, nchste mgliche Ausfhrungszeit setzen
                                            if pItem.SendIntervall > 0:
                                                pItem.Ausgang[out][0] = time.time() + pItem.SendIntervall
                                            ## Ausgangswert auch in der Logik setzen
                                            pItem.OutWert[out] = value
                                
                                
                                ## Das ist die Class und muss hier immer rein anstelle von frher SN[1]
                                Netatmo_OAUTH213554(pItem)
                                ​

                                Kommentar

                                Lädt...
                                X