Ankündigung

Einklappen
Keine Ankündigung bisher.

Interesse an HomeConnect Plugin?

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

    #61
    OK. kein Stress.
    kämpfe zurzeit an mehreren Fronten mit Software-Tücken.
    Da wird mal wieder deutlich, wie sorgfältig Software entwickelt wird, aber auch, wie anfällig solche Systeme sind.

    Kommentar


      #62
      Hallo psilo ,

      bist du in der dunklen Jahreszeit weiter gekommen?

      Viele Grüße,
      Hendrik

      Kommentar


        #63
        Hi,

        an alle die hier vieleicht was tun möchten - ich habe mal die OAuth-Identifizierung durchgespielt, mit folgendem Code-Snippet bekommt man einen access/refresh-Token. Alles "pure-requests".

        Die Daten im Kopf entsprechend den Angaben in der Home-Connect-Developer Konsole eintragen. Ich hatte zum testen als Redirect-URL "https://www.smarthomeng.de" angegeben. Die Redirect-URL muss beim erstellen der Applikation in der Cloud von Anfang an korrekt sein. Nachträglich ändern geht schief da diese irgendwie in Client-ID und Client-Secret "gehasht" wird. Beim Ändern wird nicht neu berechnet, d.h. ClientId und ClientSecret passen nicht zur redirect-URI.

        Ich habe den Code noch um eine Funktion für Token-Refresh ergänzt.

        Vielleicht kann es ja jemand brauchen

        Code:
        import json
        import requests
        import urllib
        import uuid
        import time
        
        ######################################
        # Your Information from HC-Cloud
        ######################################
        hc_ClientId = '<YOUR_CLIENT_ID>'
        hc_email = '<YOUR_MAIL_ADRESS>'
        hc_pwd = '<YOUR_PASSWORD>'
        hc_Scope = '<YOUR_SCOPE>' # -> "IdentifyAppliance Monitor Control Images Settings" for all
        hc_ClientSecret = '<YOUR_CLIENT_SECRET>'
        hc_redirect_URI = '<YOUR_REDIRECT_URL>
        
        
        def getToken():
            myHeader={
                        'Host'              : 'api.home-connect.com',
                        'User-Agent'        : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:96.0) Gecko/20100101 Firefox/96.0',
                        'Accept'            : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
                        'Accept-Language'   : 'de,en-US;q=0.7,en;q=0.3',
                        'Accept-Encoding'   : 'gzip, deflate, br',
                        'Content-Type'      : 'application/x-www-form-urlencoded',
                        'Host'              : 'api.home-connect.com'
                    }
        
        
            # Login to get a Code for getting a Token
        
            myData = {'client_id'       : hc_ClientId,
                      'redirect_uri'    : hc_redirect_URI,
                      'response_type'   : 'code',
                      'scope'           : hc_Scope,
                      'state'           : uuid.uuid4().hex
                      }
            postfields = urllib.parse.urlencode(myData)
            mySession = requests.session()
            myResponse = mySession.get('https://api.home-connect.com/security/oauth/authorize',params=postfields,headers=myHeader)
        
            if myResponse.status_code != 200:
                 print ('cold not get Login-Form : ' + myResponse.status_code)
        
            myLines = (myResponse.content.decode()).split("\n")
            for myString in myLines:
                if 'hidden' in myString:
                    myArray = myString.split(" ")
                    if 'name="sessionId"' in myArray:
                        mySessionId=myArray[(myArray.index('name="sessionId"')+1)].replace("/>","").split("=")[1].replace('"','')
                    if 'name="sessionData"' in myArray:
                        mySessionData=myArray[(myArray.index('name="sessionData"')+1)].replace("/>","").split('"')[1]
                    if 'name="client_id"' in myArray:
                        myClientId=myArray[(myArray.index('name="client_id"')+1)].replace("/>","").split("=")[1].replace('"','')
                    if 'name="region"' in myArray:
                        myRegion=myArray[(myArray.index('name="region"')+1)].replace("/>","").split("=")[1].replace('"','')
                    if 'name="environment"' in myArray:
                        myEnvironment=myArray[(myArray.index('name="environment"')+1)].replace("/>","").split("=")[1].replace('"','')
        
        
            myData = {
                        'sessionId'         : mySessionId,
                        'sessionData'       : mySessionData,
                        'aborted'           : False,
                        'client_id'         : myClientId,
                        'accept_language'   : 'de',
                        'region'            : myRegion,
                        'environment'       : myEnvironment,
                        'email'             : hc_email,
                        'password'          : hc_pwd
                     }
            postfields = urllib.parse.urlencode(myData)
            myResponse = mySession.post('https://api.home-connect.com/security/oauth/login',data=postfields,headers=myHeader)
        
            if myResponse.status_code != 200:
                 print ('cold not Login : ' + str(myResponse.status_code))
        
            myData = {
                        'sessionId'         : mySessionId,
                        'aborted'           : False,
                        'accept_language'   : 'de',
                        'client_id'         : myClientId,
                        'email'             : hc_email,
                        'region'            : myRegion,
                        'environment'       : myEnvironment,
                        'scope'             : hc_Scope
                     }
            postfields = urllib.parse.urlencode(myData)
        
            myResponse = requests.post('https://api.home-connect.com/security/oauth/grant',data=postfields,headers=myHeader,allow_redirects=False)
        
            if myResponse.status_code != 302:
                 print ('cold not get grant-access : ' + str(myResponse.status_code))
        
            myLocation = urllib.parse.unquote(myResponse.headers['Location'])
        
            myCode          = myLocation.split("?")[1].split("&")[0].split(("="))[1]
            my_grant_type   = myLocation.split("?")[1].split("&")[2].split(("="))[1]
            my_state        = myLocation.split("?")[1].split("&")[1].split(("="))[1]
        
            # Now get the Token
            myData = {
                        'client_id'         : myClientId,
                        'client_secret'     : hc_ClientSecret,
                        'redirect_uri'      : hc_redirect_URI,
                        'grant_type'        : my_grant_type,
                        'code'              : myCode
                     }
            postfields = urllib.parse.urlencode(myData)
            myResponse = requests.post('https://api.home-connect.com/security/oauth/token',data=postfields,headers=myHeader,allow_redirects=False)
        
            if myResponse.status_code != 200:
                 print ('cold not get access-Token : ' + str(myResponse.status_code))
            else:
                myBearerDict = json.loads(myResponse.content.decode())
                myAccessToken  = myBearerDict['access_token']
                myRefreshToken = myBearerDict['refresh_token']
                myExperition   = myBearerDict['expires_in']
                myIdToken      = myBearerDict['id_token']
                myTokenType    = myBearerDict['token_type']
                print ('Got Access/Refresh-Token - Acces-Token : ' + myAccessToken )
                return myAccessToken,myRefreshToken
        
        def get_refresh_Token(refresh_Token):
            #grant_type=refresh_token&refresh_token={refresh_token}&client_secret={client_secret}
            myHeader={
                    'Host'              : 'api.home-connect.com',
                    'User-Agent'        : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:96.0) Gecko/20100101 Firefox/96.0',
                    'Accept'            : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
                    'Accept-Language'   : 'de,en-US;q=0.7,en;q=0.3',
                    'Accept-Encoding'   : 'gzip, deflate, br',
                    'Content-Type'      : 'application/x-www-form-urlencoded',
                    'Host'              : 'api.home-connect.com'
                }
            myData = {
                        'grant_type'        : 'refresh_token',
                        'refresh_token'     : refresh_Token,
                        'client_secret'      : hc_ClientSecret
                     }
            postfields = urllib.parse.urlencode(myData)
            myResponse = requests.post('https://api.home-connect.com/security/oauth/token',data=postfields,headers=myHeader,allow_redirects=False)
            if myResponse.status_code != 200:
                 print ('cold not get new access-Token : ' + str(myResponse.status_code))
            else:
                myBearerDict = json.loads(myResponse.content.decode())
                myAccessToken  = myBearerDict['access_token']
                myRefreshToken = myBearerDict['refresh_token']
                return myAccessToken, myRefreshToken
        
        if __name__ == '__main__':
            myToken, myRefreshToken = getToken()
            time.sleep(10)
            myNewToken, myNewRefreshToken = get_refresh_Token(myRefreshToken)
            print ('new Token : ' + myNewToken)
        Viele Grüsse
        Andre
        Zuletzt geändert von AndreK; 31.01.2022, 22:20. Grund: Code für Refresh-Token ergänzt

        Kommentar


          #64
          Moin,

          ganz fresh: https://github.com/osresearch/hcpy/tree/singlekey
          Damit ist der Zugriff auf ein BSH "Home-Connect" Geschirrspüler ohne dauerhafte Cloud-Verbindung möglich.

          Zur Erstellung des initialen "config.json" benötigt man User+Pass+Cloud, und anschließend eben nicht mehr :-)
          Ein Beispiel-Script schiebt den Status dann via MQTT weiter.

          Ein kleiner Vorgeschmack, welche Infos sichtbar sind.

          Code:
          2023-03-13 19:08:43.443847 {'DoorState': 'Open', 'ProgramFinished': 'Off'}
          publish homeconnect/dishwasher {"state": "Inactive", "door": "Open", "remaining": "0:00", "power": false, "lowwaterpressure": false, "aquastop": false, "error": false, "remainingseconds": 0}
          2023-03-13 19:08:48.252266 {'AllowBackendConnection': True, 'BackendConnected': False, 'SoftwareUpdateAvailable': 'Off', 'ActiveProgram': 0, 'SelectedProgram': 8196, '515': False, '516': False, 'RemoteControlStartAllowed': False, 'AllowFlexStart': False, 'ApplianceTime': '19:08:47', 'RemoteControlActive': True, '524': False, 'AquaStopOccured': 'Off', 'DoorState': 'Open', 'CustomerEnergyManagerPaired': False, '532': False, 'Language': 'De', '534': False, 'PowerState': 'On', 'ProgramFinished': 'Off', 'ProgramProgress': 0, 'LowWaterPressure': 'Off', 'RemainingProgramTime': 12900, 'ProgramAborted': 'Off', 'SynchronizeWithTimeServer': True, 'OperationState': 'Ready', 'CustomerServiceConnectionAllowed': False, 'StartInRelative': 0}
          publish homeconnect/dishwasher {"state": "Ready", "door": "Open", "remaining": "3:35", "power": true, "lowwaterpressure": false, "aquastop": false, "error": false, "remainingseconds": 12900}
          2023-03-13 19:08:48.385299 {'CustomerServiceRequest': 'Off', 'EnergyForecast': 36, 'WaterForecast': 48, 'FlexStart': 'Disabled', 'FlexStartInRelative': 0, 'TimeFormat': '24Hours', '587': True, '588': 100, '589': 0, '590': '#000000', '591': 0, 'SoftwareUpdateTransactionID': 0, 'SoftwareDownloadAvailable': 'Off', 'SoftwareUpdateSuccessful': 'Off', 'ProgramPhase': 'None', '4097': 255, '4098': 255, '4099': 0, '4352': 0, 'RelAbsOperatingTime': 'Absolute', 'RinseAid': 'R03', 'SensitivityTurbidity': 'Standard', 'ExtraDry': True, 'HotWater': 'HotWater', 'EcoPrognosis': True, '4359': 1, '4360': True, '4361': True}
          2023-03-13 19:08:48.501947 {'TimeLight': 'On', 'EcoAsDefault': 'LastProgram', 'SoundLevelSignal': 'Low', 'SoundLevelKey': 'Low', 'BrandLogo': False, 'WaterHardness': 'H04', '4368': False, '4376': False, '4377': True, '4378': True, '4379': True, '4381': 1, 'InternalError': 'Off', 'CheckFilterSystem': 'Off', 'DrainingNotPossible': 'Off', 'DrainPumpBlocked': 'Off', 'WaterheaterCalcified': 'Off', 'LowVoltage': 'Off', 'SaltLack': 'Off', 'RinseAidLack': 'Off', 'SaltNearlyEmpty': 'Off', 'RinseAidNearlyEmpty': 'Off', 'MachineCareReminder': 'Off', '4629': 0, '4630': 0, '4631': 0, '4632': 0, '4633': 0, '4640': 0, '4641': 0, '5120': False, '5121': False, '5122': False}
          publish homeconnect/dishwasher {"state": "Ready", "door": "Open", "remaining": "3:35", "power": true, "lowwaterpressure": false, "aquastop": false, "error": false, "remainingseconds": 12900}
          2023-03-13 19:08:48.584275 {'5123': False, '5124': False, '5125': False, 'IntensivZone': False, 'VarioSpeedPlus': False, 'BrillianceDry': False, '5129': False, '5130': False, '5131': False, '5132': False, '5133': False, '5134': False, '5135': False}
          2023-03-13 19:08:49.648937 {'AllowFlexStart': False, 'FlexStartInRelative': 0, '588': 100, '590': '#000000', 'SoftwareUpdateTransactionID': 0, '4099': 0}
          2023-03-13 19:09:00.343002 {'PowerState': 'Off', 'OperationState': 'Inactive'}
          publish homeconnect/dishwasher {"state": "Inactive", "door": "Open", "remaining": "3:35", "power": false, "lowwaterpressure": false, "aquastop": false, "error": false, "remainingseconds": 12900}
          2023-03-13 19:09:03.526100 {'DoorState': 'Closed'}
          publish homeconnect/dishwasher {"state": "Inactive", "door": "Closed", "remaining": "3:35", "power": false, "lowwaterpressure": false, "aquastop": false, "error": false, "remainingseconds": 12900}
          Aktuell wird nur die letzte Zeile via MQTT ausgegeben..

          Kommentar

          Lädt...
          X