[ECMA] Trying to get response on a https POST request

I’m trying to renew an API-Token via a rule. The following code worked via POSTMAN, however I’m failing in an ECMA rule.

var headers = [];
headers["Content-Type"] = "application/x-www-form-urlencoded";
var returnvalue = HTTP.sendHttpPostRequest("https://iam.viessmann.com/idp/v2/token", "application/x-www-form-urlencoded","grant_type=refresh_token&client_id=my_client_id&refresh_token=my_refresh_token",headers, 10*1000);

Do I need to encode the url?
Are the Query Params (field naming of Postman) (“grant_type=refresh_token&client_id=my_client_id&refresh_token=my_refresh_token”) placed correctly into the content?

…Yes, the my_client_id and my_refresh_token are placeholders for my actual keys!

I’m initially trying to do such in a rule, the final goal is a binding for Viessmann VitoConnect!

I don’t think you have the headers and content type stuff correct.

From the docs:

sendHttpPostRequest(String url, String contentType, String content, Map<String, String> headers, int timeout)

You have the url and the content type in the call. But you’ve also added the content type to the headers which is redundant.

One thing that seems to be missing is any sort of authentication. Perhaps you need to put that into the header?

One thing I don’t know is whether or not the engine is able to handle converting the JavaScript Dict to a Java Map. HTTP is a Java Object so it needs a Java Map. It might not know how to handle the conversion between the two types.

Here is a snippet of code where I do something similar for the Honeywell Home API. The full code and explanations are at Honeywell Home API with openHAB using just rules.

/**
 * Generates a request for a new auth token and refresh token.
 * @param {boolean} refresh Optional flag that defaults to true. When true the request 
 *   is made using the refresh token. When false the request is made using the access 
 *   code.
 * @return {boolean} true if the request was successful, false otherwise
 */
var requestAuthToken = function(refresh){
  refresh = refresh || true;

  if(refresh && items["Honeywell_RefreshToken"].class === UnDefType.class){
    logger.error("Refresh token is undefined!");
    return false;
  }
  else if(!refresh && items["Honeywell_AuthCode"].class === UnDefType.class){
    logger.error("Auth code is undefined!");
    return false;
  }

  var TOKEN_URL = "https://api.honeywell.com/oauth2/token";
  var GT_AUTHCODE = "grant_type="+((refresh) ? "refresh_token" : "authorization_code");
  var REDIRECT_URL = "redirect_uri=https%3A%2F%2Fmyopenhab.org%2Fstatic%2Foauth2.html";
  var CODE = (refresh) ? "refresh_token="+items["Honeywell_RefreshToken"] : REDIRECT_URL+"&code="+items["Honeywell_AuthCode"];

  var authEncoded = encodeAuth();

  // Build the header
  var header = new HashMap();
  header.put("Authorization", "Basic " + authEncoded);
  header.put("Accept", "application/json");

  var results = HTTP.sendHttpPostRequest("https://api.honeywell.com/oauth2/token",
                                         "application/x-www-form-urlencoded",
                                         GT_AUTHCODE+"&"+CODE,
                                         header,
                                         15000);

  logger.debug("Results from request for auth token: " + results);
  if(results !== null && results != "" && results !== undefined) {
    processAuth(results);
    return true;
  }
  else {
    logger.error("Failed to retrieve auth token!");
    return false;
  }

};

Notice how I put an Authorization entry into the header. For the Honeywell API that consists of <client key>:<client secret> encoded with Base64.

1 Like

BINGO!
Removed the redundant headers and it worked! No authentification needed for that call, it calls for an Key to be used for further calls.

Thanks!