Apollon77 / daikin-controller-cloud

Connect and Control Daikin Cloud devices
MIT License
98 stars 25 forks source link

RequestError: Unexpected retry option: retries #97

Closed tgu-git closed 1 year ago

tgu-git commented 1 year ago

I'd like to retrieve the token from the Daikins Cloud Service using your tokensaver.js script.

I did a git clone from your git repo.

When I execute the tokensaver.js script while providing my Dakin user credentials (mail address + password) I'll receive the following exeption:

/daikin-controller-cloud $ node example/tokensaver.js "<mail-address>" "<password>"
Writing tokenset to: /home/openhabian/Daikin/daikin-controller-cloud/tokenset.json
Using provided Login credentials (<mail-adress>/<password>) for a direct Login
node:internal/process/promises:279
            triggerUncaughtException(err, true /* fromPromise */);
            ^
RequestError: Unexpected retry option: retries
    at Request._destroy (/home/openhabian/Daikin/daikin-controller-cloud/node_modules/@esm2cjs/got/build/cjs/core/index.js:482:15)
    at _destroy (node:internal/streams/destroy:102:25)
    at Request.destroy (node:internal/streams/destroy:64:5)
    at Request.flush (/home/openhabian/Daikin/daikin-controller-cloud/node_modules/@esm2cjs/got/build/cjs/core/index.js:265:14)
    at lastHandler (/home/openhabian/Daikin/daikin-controller-cloud/node_modules/@esm2cjs/got/build/cjs/create.js:63:20)
    at iterateHandlers (/home/openhabian/Daikin/daikin-controller-cloud/node_modules/@esm2cjs/got/build/cjs/create.js:76:22)
    at got (/home/openhabian/Daikin/daikin-controller-cloud/node_modules/@esm2cjs/got/build/cjs/create.js:94:12)
    at DaikinCloudController.login (/home/openhabian/Daikin/daikin-controller-cloud/index.js:320:36)
    at main (/home/openhabian/Daikin/daikin-controller-cloud/example/tokensaver.js:55:50)
    at /home/openhabian/Daikin/daikin-controller-cloud/example/tokensaver.js:80:12
    at Options.set retry [as retry] (/home/openhabian/Daikin/daikin-controller-cloud/node_modules/@esm2cjs/got/build/cjs/core/options.js:889:15)
    at Options.merge (/home/openhabian/Daikin/daikin-controller-cloud/node_modules/@esm2cjs/got/build/cjs/core/options.js:419:19)
    at new Options (/home/openhabian/Daikin/daikin-controller-cloud/node_modules/@esm2cjs/got/build/cjs/core/options.js:372:16)
    at new Request (/home/openhabian/Daikin/daikin-controller-cloud/node_modules/@esm2cjs/got/build/cjs/core/index.js:249:22)
    at got (/home/openhabian/Daikin/daikin-controller-cloud/node_modules/@esm2cjs/got/build/cjs/create.js:58:21)
    at DaikinCloudController.login (/home/openhabian/Daikin/daikin-controller-cloud/index.js:320:36)
    at main (/home/openhabian/Daikin/daikin-controller-cloud/example/tokensaver.js:55:50)
    at /home/openhabian/Daikin/daikin-controller-cloud/example/tokensaver.js:80:12
    at Object.<anonymous> (/home/openhabian/Daikin/daikin-controller-cloud/example/tokensaver.js:81:4)
    at Module._compile (node:internal/modules/cjs/loader:1155:14) {
  input: undefined,
  code: 'ERR_GOT_REQUEST_ERROR',
  timings: undefined,
  options: Options {
    _unixOptions: undefined,
    _internals: {
      request: undefined,
      agent: { http: undefined, https: undefined, http2: undefined },
      h2session: undefined,
      decompress: true,
      timeout: {
        connect: undefined,
        lookup: undefined,
        read: undefined,
        request: 10000,
        response: 10000,
        secureConnect: undefined,
        send: undefined,
        socket: undefined
      },
      prefixUrl: '',
      body: undefined,
      form: undefined,
      json: undefined,
      cookieJar: undefined,
      ignoreInvalidCookies: false,
      searchParams: undefined,
      dnsLookup: undefined,
      dnsCache: undefined,
      context: {},
      hooks: {
        init: [],
        beforeRequest: [],
        beforeError: [],
        beforeRedirect: [],
        beforeRetry: [],
        afterResponse: []
      },
      followRedirect: false,
      maxRedirects: 10,
      cache: undefined,
      throwHttpErrors: true,
      username: '',
      password: '',
      http2: false,
      allowGetBody: false,
      headers: { 'user-agent': 'got (https://github.com/sindresorhus/got)' },
      methodRewriting: false,
      dnsLookupIpVersion: undefined,
      parseJson: [Function: parse],
      stringifyJson: [Function: stringify],
      retry: {
        limit: 2,
        methods: [ 'GET', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'TRACE' ],
        statusCodes: [
          408, 413, 429, 500,
          502, 503, 504, 521,
          522, 524
        ],
        errorCodes: [
          'ETIMEDOUT',
          'ECONNRESET',
          'EADDRINUSE',
          'ECONNREFUSED',
          'EPIPE',
          'ENOTFOUND',
          'ENETUNREACH',
          'EAI_AGAIN'
        ],
        maxRetryAfter: undefined,
        calculateDelay: [Function: calculateDelay],
        backoffLimit: Infinity,
        noise: 100
      },
      localAddress: undefined,
      method: 'GET',
      createConnection: undefined,
      cacheOptions: {
        shared: undefined,
        cacheHeuristic: undefined,
        immutableMinTimeToLive: undefined,
        ignoreCargoCult: undefined
      },
      https: {
        alpnProtocols: undefined,
        rejectUnauthorized: undefined,
        checkServerIdentity: undefined,
        certificateAuthority: undefined,
        key: undefined,
        certificate: undefined,
        passphrase: undefined,
        pfx: undefined,
        ciphers: undefined,
        honorCipherOrder: undefined,
        minVersion: undefined,
        maxVersion: undefined,
        signatureAlgorithms: undefined,
        tlsSessionLifetime: undefined,
        dhparam: undefined,
        ecdhCurve: undefined,
        certificateRevocationLists: undefined
      },
      encoding: undefined,
      resolveBodyOnly: false,
      isStream: false,
      responseType: 'text',
      url: <ref *1> URL {
        [Symbol(context)]: URLContext {
          flags: 912,
          scheme: 'https:',
          username: '',
          password: '',
          host: 'daikin-unicloud-prod.auth.eu-west-1.amazoncognito.com',
          port: null,
          path: [ 'oauth2', 'authorize' ],
          query: 'client_id=7rk39602f0ds8lk0h076vvijnb&scope=openid&response_type=code&redirect_uri=daikinunified%3A%2F%2Flogin&scopes=email%2Copenid%2Cprofile&state=6oHPJZH4Ozdjba5x9SOkE2Ugyjtxml4-d9bxyrYEz_8&code_challenge=kB8rBX5EwBI7fKcAB05_Kr3OO_2Eft1tJnTtymiVqi4&code_challenge_method=S256',
          fragment: null
        },
        [Symbol(query)]: URLSearchParams {
          [Symbol(query)]: [
            'client_id',
            '7rk39602f0ds8lk0h076vvijnb',
            'scope',
            'openid',
            'response_type',
            'code',
            'redirect_uri',
            'daikinunified://login',
            'scopes',
            'email,openid,profile',
            'state',
            '6oHPJZH4Ozdjba5x9SOkE2Ugyjtxml4-d9bxyrYEz_8',
            'code_challenge',
            'kB8rBX5EwBI7fKcAB05_Kr3OO_2Eft1tJnTtymiVqi4',
            'code_challenge_method',
            'S256'
          ],
          [Symbol(context)]: [Circular *1]
        }
      },
      pagination: {
        transform: [Function: transform],
        paginate: [Function: paginate],
        filter: [Function: filter],
        shouldContinue: [Function: shouldContinue],
        countLimit: Infinity,
        backoff: 0,
        requestLimit: 10000,
        stackAllItems: false
      },
      setHost: true,
      maxHeaderSize: undefined,
      signal: undefined,
      enableUnixSockets: true
    },
    _merging: false,
    _init: []
  }
}

System information: $ node --version v16.18.1

$ cat /etc/debian_version 11.5

I'd like to write my own script until an OpenHAB Daikin binding is provided supporting Daikin Cloud Credentials.

Apollon77 commented 1 year ago

Honestly .. maybe try to use valid email and password first? I could very good assume that the > and < is making such an issue.

tgu-git commented 1 year ago

Of corse I put my valid credentials in the CLI, but didn't share them here at git. Thus I put the placeholders only here. Could the reason for the excepetion my password as it starts with a '^'?

tgu-git commented 1 year ago

Behavior is the same if I use my valid mail address and a random password without any special character.

Apollon77 commented 1 year ago

Ok, which version of the library did you install?

Apollon77 commented 1 year ago

Hm ... It seems that got changed a parametrr a... will fix that ... grmppfff

RobMeerwijk commented 1 year ago

I get the same error. Have you made a fix yet? Thanks for your answer!

Apollon77 commented 1 year ago

not yet, hopefully soon. Time is rare becfause of other prios right now

RobMeerwijk commented 1 year ago

Ok, no problem!

skycrack-77 commented 1 year ago

Okay, since today i have the same Issue, "HTTPError: Response code 400 (Bad Request)" without any changes in configuration. Is there any Workarround to get an fuctionality state ? Best Regards Rene

Apollon77 commented 1 year ago

Yes get new tokens

RobMeerwijk commented 1 year ago

That is what I tried to do, but it failed with the above error.

Apollon77 commented 1 year ago

Hhm ... amybe they changed something in their flow and we need to adjust :-(

skycrack-77 commented 1 year ago

node example/tokensaver.js "<mail-addresse>" "<password>" solve the" Bad Request" Issue. Thanks for the amazing Daikin Module :-)

tgu-git commented 1 year ago

Just tryed again, but for me the situation is unchanged. Still get code: 'ERR_GOT_REQUEST_ERROR' @skycrack-77 For you it is working, to retrieve the token?

RobMeerwijk commented 1 year ago

I still can´t get a token. Related: https://github.com/ksacca/daikincloud-domoticz/issues/1 This git is based on daikin-controller-cloud. Using this node red flow I can´t login with or without saving a token.

RedErk commented 1 year ago

Had the same problem "ERR_GOT_REQUEST_ERROR" on refreshAccessToken().

postman got the correct response.

I have replaced the call in refreshAccessToken with standard node https request:

This fixed the problem for me.

//-------------------------------------------------------------------------
//-- node https standard call
//-------------------------------------------------------------------------
async doRequestRefreshAccessToken()
{
  return new Promise ((resolve, reject) =>
  {
    var options = {
      'method': 'POST',
      'hostname': 'cognito-idp.eu-west-1.amazonaws.com',
      'path': '/',
      'headers': {
        'Content-Type': 'application/x-amz-json-1.1',
        'x-amz-target': 'AWSCognitoIdentityProviderService.InitiateAuth',
        'x-amz-user-agent': 'aws-amplify/0.1.x react-native',
        'User-Agent': 'Daikin/1.6.1.4681 CFNetwork/1220.1 Darwin/20.3.0'
      },
      'maxRedirects': 20
    };

    var req = https.request(options, function (res)
    {
      var chunks = [];

      res.on("data", function (chunk) {
        chunks.push(chunk);
      });

      res.on("end", function (chunk) {
        var body = Buffer.concat(chunks);
        resolve(body.toString());
      });

      res.on("error", function (error) {
        reject(error);
      });
    });

    var oPostData = 
    {
      'ClientId': this.openIdClientId,
      'AuthFlow': 'REFRESH_TOKEN_AUTH',
      'AuthParameters': {
          'REFRESH_TOKEN': this.tokenSet.refresh_token
      }
    }
    req.write(JSON.stringify(oPostData));
    req.end();
  }); 
}
//-------------------------------------------------------------------------

/**
 * Refresh the tokens
 * This method normally is called automatically if a 401 response is received,
 * so should not be needed to be called manually
 *
 * On Error the got response is included as property "response"  in Error object
 *
 * @emits DaikinCloudController#token_update
 * @returns {Promise<TokenSet>}
 */
async refreshAccessToken() {
    //----------------
    //-- replace code
    //----------------
    let strResponseCall = await this.doRequestRefreshAccessToken();
    let response = {};
    response.body = JSON.parse(strResponseCall);

    //-----------------
    //-- replaced code
    //-----------------
    //const response = await got.post('https://cognito-idp.eu-west-1.amazonaws.com', {
    //    headers: {
    //        'Content-Type': 'application/x-amz-json-1.1',
    //        'x-amz-target': 'AWSCognitoIdentityProviderService.InitiateAuth',
    //        'x-amz-user-agent': 'aws-amplify/0.1.x react-native',
    //        'User-Agent': 'Daikin/1.6.1.4681 CFNetwork/1220.1 Darwin/20.3.0'
    //    },
    //    json: {
    //        'ClientId': this.openIdClientId,
    //        'AuthFlow': 'REFRESH_TOKEN_AUTH',
    //        'AuthParameters': {
    //            'REFRESH_TOKEN': this.tokenSet.refresh_token
    //        }
    //    },
    //    responseType: 'json',
    //    hooks: {
    //        beforeRequest: [
    //            (options) => {
    //                if (this.options.logLevel === 'debug') {
    //                    console.log('<-- %s %s', options.method.toUpperCase(), options.url.href);
    //                    console.log('<-- HEADERS %o', options.headers);
    //                    if (options.body) {
    //                        console.log('<-- BODY %s', options.body);
    //                    }
    //                }
    //            },
    //        ],
    //        afterResponse: [
    //            (response) => {
    //                if (this.options.logLevel === 'debug') {
    //                    console.log('--> %i FROM %s %s', response.statusCode, response.request.options.method.toUpperCase(), response.request.options.url.href);
    //                    console.log('--> HEADERS %o', response.headers);
    //                    if (response.body) {
    //                        console.log('--> BODY %s', response.body);
    //                    }
    //                }
    //                return response;
    //            }
    //        ]
    //    },
    //    timeout: {
    //        response: this.options.communicationTimeout,
    //        request: this.options.communicationTimeout
    //    },
    //    retry: {
    //        retries: this.options.communicationRetries,
    //        errorCodes: ['ETIMEDOUT'],
    //        methods: ['GET', 'POST']
    //    }
    //});

    if (response.body && response.body.AuthenticationResult && response.body.AuthenticationResult.AccessToken && response.body.AuthenticationResult.TokenType === 'Bearer') {
        this.tokenSet.access_token = response.body.AuthenticationResult.AccessToken;
        this.tokenSet.id_token = response.body.AuthenticationResult.IdToken;
        this.tokenSet.access_token = response.body.AuthenticationResult.AccessToken;
        this.tokenSet.expires_at = ~~(Date.now() / 1000) + response.body.AuthenticationResult.ExpiresIn * 1000;
        this.emit('token_update', this.tokenSet);
        return this.tokenSet;
    }
    const err = new Error('Token refresh was not successful! ' + response.statusCode);
    err.response = response;
    throw err;
}
RedErk commented 1 year ago

var https = require('follow-redirects').https;

on file head needed