Error at "execute an action on a device"

Hi,

I tried to “execute an action on a device” for study but “400 Bad request” returned.
I checked ‘device ID’ and ‘account ID’ in request URL and ‘access token’ in header but I can not find any errors.
I may misunderstand something. Could you tell me advice?

I attach tconsole.log(png) and header(png).

I try to upload my source program file but this forum can not accept text file and zip file.
So I paste my javascript program source in this topic.

Thank you.
Kazu.

==== source program ======
Sorry. I can not paste program normally. Topic editor analyze html tags. I will fix them.

I fixed. Cause is blank lines.

<html> <body> <script type="text/javascript"> var access_token; var accountId; var result; var deviceNum; var deviceId = new Array(); // authenticateUser("xxxxxxxxx@xxxxx.jp", "xxxxxxxxxxx") .then(function (result) { access_token = result.access_token console.log(access_token); return getUserInfo(result.access_token); // }).then(function (result) { console.log(result.toSource()); accountId = result.accountAccess[0].account.accountId; return getCurrentDevices(access_token, accountId); // }).then(function (result) { console.log(result.toSource()); deviceNum=result.length; console.log(deviceNum); for(iii=0;iii<deviceNum;iii++){ deviceId[iii] = result[iii].deviceId; } console.log(deviceId); return getCurrentTagsOfDevices(access_token, accountId); // }).then(function (result) { console.log(result.toSource()); return getCurrentStateOfDevices(access_token, accountId); // }).then(function (result) { // return getCurrentAttributesOfDevices(access_token, accountId); // }).then(function (result) { console.log(result.toSource()); return ExecuteActionDevice(access_token, accountId, deviceId[0]); // }).then(function (result) { console.log(result.toSource()); // }).catch(function (e) { // console.log(e); }); // // // Get OAuth token, instant gratification example function authenticateUser(username, password) { return new Promise(function (resolve, reject) { var tokenUrl = "https://api.afero.io/oauth/token"; var basicAuthorizationValue = btoa("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); var requestBody = "grant_type=password&username=" + encodeURIComponent(username) + "&password=" + encodeURIComponent(password); // var xhr = new XMLHttpRequest(); xhr.open('POST', tokenUrl, true); xhr.setRequestHeader("Authorization", "Basic " + basicAuthorizationValue); xhr.setRequestHeader('Content-Type', "application/x-www-form-urlencoded"); xhr.responseType = 'json'; // xhr.onload = function () { if (this.status >= 200 && this.status <= 299) { resolve(this.response); } else { reject(this.statusText); } return(this); // }; xhr.onerror = function (e) { reject(this.statusText); }; console.log(requestBody); xhr.send(requestBody); }); } // function getUserInfo(accessToken) { return new Promise(function (resolve, reject) { var tokenUrl = "https://api.afero.io/v1/users/me"; var xhr = new XMLHttpRequest(); xhr.open('GET', tokenUrl, true); xhr.setRequestHeader("Authorization", "Bearer " + accessToken); xhr.setRequestHeader('Content-Type', "application/json"); xhr.responseType = 'json'; // xhr.onload = function () { if (this.status >= 200 && this.status <= 299) { resolve(this.response); } else { reject(this.statusText); } return(this); // }; xhr.onerror = function (e) { reject(this.statusText); }; xhr.send(); }); } // function getCurrentDevices(accessToken, accountId) { return new Promise(function (resolve, reject) { var tokenUrl = "https://api.afero.io/v1/accounts/" + accountId + "/devices" ; var xhr = new XMLHttpRequest(); xhr.open('GET', tokenUrl, true); xhr.setRequestHeader("Authorization", "Bearer " + accessToken); xhr.setRequestHeader('Content-Type', "application/json"); xhr.responseType = 'json'; xhr.onload = function () { if (this.status >= 200 && this.status <= 299) { resolve(this.response); } else { reject(this.statusText); } return(this); // }; xhr.onerror = function (e) { reject(this.statusText); }; xhr.send(); }); } // function getCurrentTagsOfDevices(accessToken, accountId) { return new Promise(function (resolve, reject) { var tokenUrl = "https://api.afero.io/v1/accounts/" + accountId + "/devices?expansions=tags" ; var xhr = new XMLHttpRequest(); xhr.open('GET', tokenUrl, true); xhr.setRequestHeader("Authorization", "Bearer " + accessToken); xhr.setRequestHeader('Content-Type', "application/json"); xhr.responseType = 'json'; xhr.onload = function () { if (this.status >= 200 && this.status <= 299) { resolve(this.response); } else { reject(this.statusText); } return(this); // }; xhr.onerror = function (e) { reject(this.statusText); }; xhr.send(); }); } // // function getCurrentStateOfDevices(accessToken, accountId) { return new Promise(function (resolve, reject) { var tokenUrl = "https://api.afero.io/v1/accounts/" + accountId + "/devices?expansions=state" ; var xhr = new XMLHttpRequest(); xhr.open('GET', tokenUrl, true); xhr.setRequestHeader("Authorization", "Bearer " + accessToken); xhr.setRequestHeader('Content-Type', "application/json"); xhr.responseType = 'json'; xhr.onload = function () { if (this.status >= 200 && this.status <= 299) { resolve(this.response); } else { reject(this.statusText); } return(this); // }; xhr.onerror = function (e) { reject(this.statusText); }; xhr.send(); }); } // // function getCurrentAttributesOfDevices(accessToken, accountId) { return new Promise(function (resolve, reject) { var tokenUrl = "https://api.afero.io/v1/accounts/" + accountId + "/devices?expansions=attributes" ; var xhr = new XMLHttpRequest(); xhr.open('GET', tokenUrl, true); xhr.setRequestHeader("Authorization", "Bearer " + accessToken); xhr.setRequestHeader('Content-Type', "application/json"); xhr.responseType = 'json'; xhr.onload = function () { if (this.status >= 200 && this.status <= 299) { resolve(this.response); } else { reject(this.statusText); } return(this); // }; xhr.onerror = function (e) { reject(this.statusText); }; xhr.send(); }); } // function ExecuteActionDevice(accessToken, accountId, deviceId2) { // console.log(accessToken); console.log(accountId); console.log(deviceId2); // return new Promise(function (resolve, reject) { // var tokenUrl = "https://api.afero.io/v1/accounts/" + accountId + "/devices/" + deviceId2 + "/actions";

              var requestBody = "type=attribute_read&attrId=3&data=01";

// var requestBody = “type=attribute_write&attrId=3&data=01”;
///
var xhr = new XMLHttpRequest();
xhr.open(‘POST’, tokenUrl, true);
xhr.setRequestHeader(“Authorization”, "Bearer " + accessToken);
xhr.setRequestHeader(‘Content-Type’, “application/json”);
xhr.setRequestHeader(‘Accept’ , “application/json”);
//
//
xhr.responseType = ‘json’;
xhr.onload = function () {
if (this.status >= 200 && this.status <= 299) {
resolve(this.response);
} else {
reject(this.statusText);
}
return(this); //
};
xhr.onerror = function (e) {
reject(this.statusText);
};
console.log(requestBody);
// document.write(requestBody);
xhr.send(requestBody);
//
});
}
//
</script>
</body>
</html>

Hi, Kazuya!

One quick thing to try, I have seen this before, instead of:

requestBody = “type=attribute_read&attrId=3&data=01”;

Can you please try to set the requestBody to:

{
type=attribute_read
attrId=3
data=01
}

(you can also try this, it should work as well)

requestBody = " { type=attribute_read,attrId=3,data=01 }";

Also, please note that an older version of the online developer documentation was wrong, the LED attribute in the Modulo is id=1024, not 3. Please see https://developer.afero.io/docs/en/?target=AttrRegistry.html for an updated list of attributes.

Please give that a try and let me know if it works for you!

Cheers,

Joe

Hi, Joe

Thank you for your reply.

It seems that it does not work.
I tried following texts and so on.
var requestBody = “type=attribute_read&attrId=1024&data=01”;
var requestBody = “type=attribute_read,&attrId=1024”;
var requestBody = " { type=attribute_read&attrId=1024 }";
var requestBody = " { type=attribute_read&attrId=1024&data=01 }";
var requestBody = " { type=“attribute_read”&attrId=1024&data=“01” }";
var requestBody = " { type=“attribute_read”&attrId=1024 }";
etc.
Cheers,
Kazuya.

Hi Kazuya,

My apologies, I wrote that stuff from memory instead of actually checking my notes. :frowning:

This string works for me for the request Body, I just tested it:

{ “type”: “attribute_write”, “attrId”: 1024, “data”: “00” }

The request parameters have to be in json format and not urlencoded.

Cheers,

Joe

Hi, Joe.

It works.
Double quotes in json texts need escapes in javascript program like following script.

var requestBody = "{ “type”: “attribute_write”, “attrId”: 1024, “data”: “01” } "; //LED OFF
var requestBody = "{ “type”: “attribute_write”, “attrId”: 1024, “data”: “00” } "; //LED ON

Thank you.
Kazuya

Hi Kazuya!

Excellent work! I’m happy that it’s working for you. Thank you also for posting your solution so other people can benefit from it. :smile:

Cheers,

Joe