Using Google Apps script to attempt to talk to my thermostat using the Ecobee API. In the below code, the value of json is "{ "status": { "code": 0, "message": "" } }". For the correct, full response, see the results of curl later in the question.
For some reason response is only getting the final element (status) out of the three results that are returned by the server (page, thermostatList, and status).
What am I missing?
Google Apps Script is as follows:
function getSettings() {
var response = fetchSettings();
var json = response.getContentText();
var data = JSON.parse(json);
// response, json, and data only show `status` result
}
function fetchSettings() {
try {
var headers = {
'Authorization': 'Bearer AUTH_TOKEN'
};
var payload = {
'selection' : {
'selectionType':'registered',
'selectionMatch': '',
'includeRuntime': 'true'
}
};
var options = {
'method': 'get',
'headers': headers,
'contentType': 'text/json',
'payload': JSON.stringify(payload);
};
var URL = 'https://api.ecobee.com/1/thermostat?format=json'
return UrlFetchApp.fetch(URL,options);
} catch(e) {
return e;
}
}
Using curl as follows:
curl -s -H 'Content-Type: text/json' -H 'Authorization: Bearer AUTH_TOKEN' 'https://api.ecobee.com/1/thermostat?format=json&body=\{"selection":\{"selectionType":"registered","selectionMatch":"",includeRuntime":true\}\}'
I get full results.
{
"page": {
"page": 1,
"totalPages": 1,
"pageSize": 2,
"total": 2
},
"thermostatList": [
{
"identifier": "12345",
"name": "Downstairs",
"thermostatRev": "160528163253",
"isRegistered": true,
"modelNumber": "athenaSmart",
"brand": "ecobee",
"features": "",
"lastModified": "2016-05-28 16:32:53",
"thermostatTime": "2016-05-28 11:57:00",
"utcTime": "2016-05-28 16:57:00",
"runtime": {
"runtimeRev": "160528165546",
"connected": true,
"firstConnected": "2015-08-20 21:57:53",
"connectDateTime": "2016-05-26 08:56:18",
"disconnectDateTime": "2016-05-26 00:00:00",
"lastModified": "2016-05-28 16:55:46",
"lastStatusModified": "2016-05-28 16:55:46",
"runtimeDate": "2016-05-28",
"runtimeInterval": 200,
"actualTemperature": 703,
"actualHumidity": 49,
"desiredHeat": 670,
"desiredCool": 810,
"desiredHumidity": 44,
"desiredDehumidity": 56,
"desiredFanMode": "on"
}
},
{
"identifier": "310166836750",
"name": "Upstairs",
"thermostatRev": "160528162656",
"isRegistered": true,
"modelNumber": "athenaSmart",
"brand": "ecobee",
"features": "",
"lastModified": "2016-05-28 16:26:56",
"thermostatTime": "2016-05-28 11:57:00",
"utcTime": "2016-05-28 16:57:00",
"runtime": {
"runtimeRev": "160528165523",
"connected": true,
"firstConnected": "2015-09-28 13:33:41",
"connectDateTime": "2016-05-26 08:55:35",
"disconnectDateTime": "2016-05-26 00:00:00",
"lastModified": "2016-05-28 16:55:23",
"lastStatusModified": "2016-05-28 16:55:23",
"runtimeDate": "2016-05-28",
"runtimeInterval": 201,
"actualTemperature": 712,
"actualHumidity": 49,
"desiredHeat": 600,
"desiredCool": 840,
"desiredHumidity": 36,
"desiredDehumidity": 60,
"desiredFanMode": "auto"
}
}
],
"status": {
"code": 0,
"message": ""
}
}
I think the problem is that UrlFetchApp doesn't support sending payload using the get method as a query string. I assume this is correct design for UrlFetchApp and poor design on the part of the Ecobee API. I made a kluge workaround by sending the JSON in a query string myself as follows.
var URL = 'https://api.ecobee.com/1/thermostat?body='+encodeURIComponent(JSON.stringify(payload));
Related
In postman I am able to log in the user and get an accessToken:
Doing Post at http://localhost:3030/authentication I type in:
{
"strategy": "local",
"email": "bob#bob.com",
"password": "bob"
}
and then I get:
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6ImFjY2VzcyJ9.eyJpYXQiOjE2NjEzMjgzMDEsImV4cCI6MTY2MTQxNDcwMSwiYXVkIjoiaHR0cHM6Ly95b3VyZG9tYWluLmNvbSIsImlzcyI6ImZlYXRoZXJzIiwic3ViIjoiMSIsImp0aSI6IjMyOWMwZTU3LTM5NTctNDUxOS05N2ZmLTRiNDIxOWI2MDQ2YSJ9.tIiRCMqzNg8F4lb1tzfYrOVvc148qRmZrZ7FPouHhKg",
"authentication": {
"strategy": "local",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6ImFjY2VzcyJ9.eyJpYXQiOjE2NjEzMjgzMDEsImV4cCI6MTY2MTQxNDcwMSwiYXVkIjoiaHR0cHM6Ly95b3VyZG9tYWluLmNvbSIsImlzcyI6ImZlYXRoZXJzIiwic3ViIjoiMSIsImp0aSI6IjMyOWMwZTU3LTM5NTctNDUxOS05N2ZmLTRiNDIxOWI2MDQ2YSJ9.tIiRCMqzNg8F4lb1tzfYrOVvc148qRmZrZ7FPouHhKg",
"payload": {
"iat": 1661328301,
"exp": 1661414701,
"aud": "https://yourdomain.com",
"iss": "feathers",
"sub": "1",
"jti": "329c0e57-3957-4519-97ff-4b4219b6046a"
}
},
"user": {
"id": 1,
"email": "bob#bob.com",
"createdAt": "2022-08-24T08:04:57.464Z",
"updatedAt": "2022-08-24T08:04:57.464Z"
}
}
But then when I try to use accessToken for another POST in Postman, I get:
{
"name": "NotAuthenticated",
"message": "Not authenticated",
"code": 401,
"className": "not-authenticated",
"errors": {}
}
Why is this?
One idea I have is maybe I did this part wrong. I thought I was supposed to add
auth.associateCurrentUser({
idField: "id",
as: "group_admin",
}),
But I was getting an error & found something online that said to change it to this (context below):
setField({
from: "params.user.id",
as: "data.group_admin",
}),
import * as authentication from "#feathersjs/authentication";
// Don't remove this comment. It's needed to format import lines nicely.
const { authenticate } = authentication.hooks;
import { setField } from "feathers-authentication-hooks";
export default {
before: {
all: [authenticate("jwt")],
find: [],
get: [],
create: [
setField({
from: "params.user.id",
as: "data.group_admin",
}),
// auth.associateCurrentUser({
// idField: "id",
// as: "group_admin",
// }),
],
update: [],
patch: [],
remove: [],
},
Do you have any ideas to get the accessToken to work with authentication?
I can post more code if needed.
I'm attempting to send a row to an appsheet app with their provided API. I have it all set up in app script and I'm getting a code 200 (success) but it's not adding the data to the spreadsheet. Am I doing something wrong?
function testingAPI(){
let appId = APP ID HERE
var url = `https://api.appsheet.com/api/v2/apps/${appId}/tables/opportunity/Action`;
var options = {
"method": "post",
"headers": {
"applicationAccessKey": ACCESS KEY HERE
},
"httpBody": {
"Action": "Add",
"Properties": {
"Locale": "en-US",
"Location": "47.623098, -122.330184",
"Timezone": "Pacific Standard Time",
"UserSettings": {
"Option 1": "value1",
"Option 2": "value2"
}
},
"Rows": [
{
"IntentionSetID": "1H3t8Dt",
"AgentID": "11234",
"ActivityID": 12,
"taskComplete": true,
"taskVerified": false,
"task_verified_by": "",
"proof": "https://drive.google.com/open?id=1CpzebeLtAljqHTsFHvVCCDFc-A6aXC3O",
"agent_expected_part_detail": "",
"poc_expected_part_detail": '',
"assigned_point_value": '',
"points_assigned_by": "10/31/2014",
"actual_part_detail": "8:15:25",
"verification_date": "18:30:33"
}
]
}
};
var response = UrlFetchApp.fetch(url, options);
console.log(response.getResponseCode())
}
I was able to find that the API call is indeed going through, but it's saying the "Action" is missing:
{
"RestAPIVersion": 2,
"TableName": "opportunity",
"AppTemplateVersion": "1.000247",
"Errors": "'Action' is missing.",
"AppTemplateName": "e280cf5a-e2de-4d24-89d3-95d384a2c044",
"Operation": "REST API invoke",
"RecordType": "Stop",
"Result": "Success",
"ResultSuccess": true,
"StatusCode": "OK"
}
changing httpBody to payload got me a step further, so now it's recognizing the "add" aspect, but it's still not understanding the properties correctly. it's showing a bunch of escape characters.
REST API:
{
"Action": "Add",
"Properties": {},
"Rows": []
}
Properties:
{
"RestAPIVersion": 2,
"TableName": "opportunity",
"AppTemplateVersion": "1.000250",
"Action": "Add",
"Errors": "API 'Properties' does not have unexpected Type of 'JObject'. Value is: '{\r\n \"Action\": \"Add\",\r\n \"Properties\": \"{Timezone=Pacific Standard Time, Location=47.623098, -122.330184, Locale=en-US}\",\r\n \"Rows\": \"[Ljava.lang.Object;#489763c2\"\r\n}'",
"AppTemplateName": "e280cf5a-e2de-4d24-89d3-95d384a2c044",
"Operation": "REST API invoke",
"RecordType": "Start",
"Result": "Failure"
}
The AppSheets API POST https://api.appsheet.com/api/v2/apps/{appId}/tables/{tableName}/Action can be used to invoke an action. This means that the action should be created in AppSheet before it can be called.
Resources
Invoke an Action | AppSheet
I am currently developping an Angular 4 chat application, which make severals HTTP request.
On Google Chrome or Opera browser, all requests work fine but when I test my app on Firefox, one of them doesn't pass. I have already cleared my cache many times but the problem persists.
this.chatWebService.getLatestConversations(params).subscribe(
(response: CustomHttpResponse<ConversationModel[]>) => {
this.chatSharedService.setDiscussionList(response.data);
},
(errorResponse: HttpErrorResponse) => {
console.log(errorResponse)
});
And the request:
public getLatestConversations(p: { filter: string, search: string, page_index: number, page_count: number }): Observable<{}> {
const url = `${this.messagesUrl}?filter=${p.filter}&search=${p.search}&page_index=${p.page_index}&page_count=${p.page_count}`;
return this.http.get(url, { params: this.createHttpParams(p) });
}
private createHttpParams(params: {}): HttpParams {
const searchParams = new HttpParams();
const keys = Object.keys(params);
keys.forEach(key => searchParams.append(key, String(params[key])));
return searchParams;
}
On Firefox, this code gives me this error:
SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of
the JSON data
Here is a sample of the returned JSON data:
{
"data": [
{
"type": "user",
"id": 76,
"name": "User 1",
"slug": "razx6k5nuser",
"muted": false,
"messages": [
{
"content": "Hi there",
"media": false,
"sent": 1516372902,
"read": true,
"sender": {
"id": 76,
"slug": "razx6k5nuser",
"lastname": "User lastname",
"firstname": "User first name",
"phoneNumber": ""
}
}
]
},
{
"type": "user",
"id": 71,
"name": "User 2",
"slug": "volc6p1suser",
"muted": false,
"messages": [
{
"content": "new message",
"media": false,
"sent": 1516358686,
"read": false,
"sender": {
"id": 77,
"slug": "razv6i2auser",
"lastname": "User lastname",
"firstname": "User first name",
"phoneNumber": ""
}
}
]
}
],
"meta": {
"page": "1",
"total": 18,
"totalNotRead": 1,
"totalMuted": 0
}
}
According to some errors I found on Google, it seems be solved by adding some headers for each request, so I have already added some headers on each of request with the interceptor, like this:
const request = req.clone({
setHeaders: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
But it still doesn't work. Can someone help me? Thank you in advance.
I have a JSON file with the following format:
const data = [
{
"quantity": "200",
"prodType": "stock",
"symbol": "LOL",
"prodDesc": "Εθνική τράπεζα",
"market": "Greece",
"averageCost": "131,16",
"totalCost": "123,47",
"lastPrice": "121,123",
"value": "123,34",
"positionPercentage": "10",
"valueEUR": "113,23",
"pl": "1300",
"plPercentage": "12",
"plEuro": "1238",
"results": "12-01-2017",
"dividend": "12-03-2017",
"isin": "1234566"
}
]
I want to filter the data using their Product Type.
As a result, im creating an action
export function fetchSearchData(product_type) {
const filtered_data = data.filter(record=>
{
return record.prodType.match(product_type)
});
return {
type: FETCH_SEARCH_DATA,
payload: filtered_data
};
}
But it does not seem to work. Do you have any idea why?
I am trying to figure out how to output a structured JSON from a query to my API. I have the following 2 tables (MySQL):
**TABLE1:**
uid
name
pptw
**TABLE2**
id
table1_uid
assignment
start_time
end_time
date
comments
And this is the JSON output I am looking for:
$scope.table1 = {
"toplevel":
[
{
"uid": 1,
"name": "john",
"pptw": "ATWF",
"child":
{
"id": 1,
"table1_uid": 1,
"assignment": null,
"start_time": "14:53:00",
"end_time": "15:00:00",
"date": null,
"comments": null
}
},
{
"uid": 22,
"name": "carol",
"pptw": "DWFF",
"child":
{
"id": 2,
"table1_uid": 22,
"assignment": null,
"start_time": "11:00:00",
"end_time": "14:00:00",
"date": null,
"comments": "Completed"
}
}
]
}
I have a promise as follow:
var request = $http({
method: 'post',
url: '.../api/v1/ppp',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
params: {
//record_uid: record_uid,
}
})
.success(function (data, status, headers, config) {
deferred.resolve(data);
})
.error(function (data, status) {
deferred.reject();
});
return deferred.promise;
And on the database, I have the following query:
SELECT tb1.uid
tb1.name
tb1.pptw,
tb2.id,
tb2.table1_uid,
tb2.assignment,
tb2.start_time,
tb2.end_time,
tb2.date,
tb2.comments
FROM
table1 tb1, table2 tb2
WHERE
tb1.uid = tb2.table1_uid
I would appreciate any ideas on how to achieve this, thanks a lot.
This is the solution to my questions, I managed to figure out how to do it. I hope it helps someone else trying to do the same thing as I did.
Here is how to create the hierarchical JSON:
var results_tree_header = [];
var results_tree = [];
if (result.rows.length > 0) {
for (var i = 0; i < result.rows.length; i++) {
results_tree.push({
"uid": result.rows.item(i).uid,
"name": result.rows.item(i).name,
"pptw": result.rows.item(i).pptw,
"child":
{
"id": result.rows.item(i).id,
"table1_uid": result.rows.item(i).table1_uid,
"assignment": result.rows.item(i).assignment,
"start_time": result.rows.item(i).start_time,
"end_time": result.rows.item(i).end_time,
"date": result.rows.item(i).date,
"comments": result.rows.item(i).comments
}
});
results_tree_header = { toplevel: results_tree };
}
}