Bill, by the way, if you have an example I can learn from, it would be great ! Many thanks.
Try this:
GoogleNestThermostat_v2.plugin (3.6 KB)
plugin.Name = "GoogleNestThermostat";
plugin.OnChangeRequest = onChangeRequest;
plugin.OnConnect = onConnect;
plugin.OnDisconnect = onDisconnect;
plugin.OnPoll = onPoll;
plugin.OnSynchronizeDevices = onSynchronizeDevices;
plugin.PollingInterval = 5000;
plugin.DefaultSettings = { "projectID": "", "clientID": "", "clientSecret": "", "refreshToken": "" };
var projectID;
var clientID;
var clientSecret;
var refreshToken;
var http = new HTTPClient();
function onChangeRequest(device, attribute, value) {
switch (attribute) {
case "Switch":
device.Switch = value;
break;
default:
break;
}
}
function onConnect() {
projectID = plugin.Settings["projectID"];
clientID = plugin.Settings["clientID"];
clientSecret = plugin.Settings["clientSecret"];
refreshToken = plugin.Settings["refreshToken"];
accessToken = null;
}
function onDisconnect() {
console.log("disconnected");
}
function onPoll() {
for (var deviceID in plugin.Devices) {
var GNThermostat = plugin.Devices[deviceID];
if (GNThermostat != null) {
if (GNThermostat.HasSubscribers()) {
if (accessToken == null) {
accessToken = HttpRefreshToken();
}
}
var getInfo = HttpGet("devices/" + deviceID);
if (!getInfo.data.error) {
var displayName = getInfo.data.parentRelations[0].displayName
var ambientTemperatureCelsius = Math.round(getInfo.data.traits["sdm.devices.traits.Temperature"].ambientTemperatureCelsius * 10) / 10;
var ambientHumidityPercent = getInfo.data.traits["sdm.devices.traits.Humidity"].ambientHumidityPercent;
var mode = getInfo.data.traits["sdm.devices.traits.ThermostatMode"].mode;
var Setpoint = Math.round(getInfo.data.traits["sdm.devices.traits.ThermostatTemperatureSetpoint"].heatCelsius * 10) / 10;
console.log("displayName = " + displayName + " , ambientTemperatureCelsius = " + ambientTemperatureCelsius + " , ambientHumidityPercent = " + ambientHumidityPercent + " , mode = " + mode + " , Setpoint = " + Setpoint);
}
GNThermostat.Temperature = ambientTemperatureCelsius;
GNThermostat.ThermostatMode = (mode == "HEAT") ? "Heat" : "Off";
GNThermostat.ThermostatOperatingState = ((ambientTemperatureCelsius - Setpoint) > 0) ? "Idle" : "Heating";
GNThermostat.HeatingSetpoint = Setpoint;
}
}
}
function onSynchronizeDevices() {
var GNThermostat = new Device();
GNThermostat.Id = "GoogleNestThermostat";
GNThermostat.DisplayName = "Google Nest Thermostat";
GNThermostat.Capabilities = ["Switch", "TemperatureMeasurement", "ThermostatMode", "ThermostatOperatingState", "HeatingSetpoint"];
GNThermostat.Attributes = [];
plugin.Devices[GNThermostat.Id] = GNThermostat;
}
function HttpGet(attribute) {
var httpHeaders = {
headers: {
'Authorization': "Bearer " + accessToken
}
};
return http.get("https://smartdevicemanagement.googleapis.com/v1/enterprises/" + projectID + "/" + attribute, httpHeaders);
}
function HttpRefreshToken() {
//console.log("getting accessToken = " + accessToken);
var TokenResult = http.post("https://www.googleapis.com/oauth2/v4/token?client_id=" + clientID + "&client_secret=" + clientSecret + "&refresh_token=" + refreshToken + "&grant_type=refresh_token");
if (!TokenResult.data.error) {
return TokenResult.data.access_token;
} else {
return null;
}
}
Bill, this works like a charm, thanks a lot!, and also many thanks for your super fast reply.
One more thing, I am using the ThermostatTile and ThermostatDetails templates, are there any templates which will work better with the Nest thermostats?
Many many thanks again!
Good to hear. Yes, ThermostatTile & ThermostatDetails are the best templates to use for this device.
Ok perfect. f you want meanwhile we wait for the official integration of the Nest thermostat I can post the plugin for others to use it… My version will not be complete thought.
Yes. Please post it.
Ok.
Sorry for another question, I would like to change the temperature and I need to make the following executeCommand:
https://smartdevicemanagement.googleapis.com/v1/enterprises/{{project-id}}/devices/{{device-id}}:executeCommand
with the following body:
data-raw ‘{
“command” : “sdm.devices.commands.ThermostatTemperatureSetpoint.SetHeat”,
“params” : {
“heatCelsius” : 22.0
}
}’
As for the headers they are:
‘Authorization: Bearer XXXX’
‘Content-Type: text/plain’
It works in Postman but I do not know how to write it in HR, this is what I came up:
function HttpPost(deviceID, capability_attribute, attribute, value) {
var httpHeaders = {
headers: {
‘Authorization’: "Bearer " + accessToken,
‘Content-Type’: “text/plain”
}
};
var body = “{command: dm.devices.commands.” + capability_attribute + “, params: {” + attribute + " : " + value + “}}”;
return http.post('https://smartdevicemanagement.googleapis.com/v1/enterprises/' + projectID + '/devices/' + deviceID + ':executeCommand', body, httpHeaders);
}
Sorry for my lack of knowledge but I do not know how to write the call.
Could you please give me a hint whenever you have some time.
Many thanks again!
This is anoher version??
function HttpPost(deviceID, capability_attribute, attribute, value) {
var httpHeaders = {
headers: {
‘Authorization’: "Bearer " + accessToken
}
};
var body = { ‘command’: “sdm.devices.commands.” + capability_attribute, params: { attribute: value } };
return http.post('https://smartdevicemanagement.googleapis.com/v1/enterprises/' + projectID + '/devices/' + deviceID + '/executeCommand', body, httpHeaders);
}
An example of the body is:
{ “command” : “sdm.devices.commands.ThermostatTemperatureSetpoint.SetHeat”, “params” : { “heatCelsius” : 22.0 } };
When embedding code in the post, can you please use the 3 back-ticks “```” at the start & end of of your code snippets?
This stuff you are sharing is hard to read.
Sorry, I pasted the code in plain text and it look like that… I am adding the plugin itself so as you could have a better look.
I tried several changes in the syntax but I always get an error…?
In addition I added the “Eco” mode in the “SupportedThermostatModes” but it does not show up in the Deatils combo?, only Heat and Off are shown.
GoogleNestThermostat.plugin (5.4 KB)
There’s a bug in SupportedThermostatModes handling for Plugins. This will be fixed in the 3.20.0.0 release. For the time being, clear the ItemsSource property on that ComboBox & set the Items directly.
This code isn’t doing what you think it is. Object keys are constants in JavaScript. “attribute” is a constant value.
var body = { 'command': "sdm.devices.commands." + capability_attribute, params: { attribute: value } };
You need to create separate functions for your attributes. You should be doing something like this instead. Hardcode the heatCelsius
value into your function.
var body = { 'command': "sdm.devices.commands." + capability_attribute, params: { heatCelsius: value } };
No luck, I am not mamaging to make it work… I am attaching the plugin again with some changes, can you please check them out?
GoogleNestThermostat.plugin (6.0 KB)
Thank you very much!
I added the list of modes manually and all of them are shown now, thanks.
Do the commands work in Postman & CURL?
Yes they do! I double check it again… I guess the problem is the syntax in HR?
By the way, the error code is 404 and accordng to API Error Code Reference | Device Access | Google Developers it can be one of these:
- A command was executed without a valid command name in the request body. Enter a valid command.
- An invalid or missing device name was specified. Specify a valid device.
- An invalid or missing Project ID was specified. Specify a valid Project ID.
This is a screen capture from Postman:
That’s not the same URL you are using in the plugin. Notice they have a colon before executeCommand & you have a slash.
Hard code temporary URLs. Test 1 thermostat. Take some of the chance for errors out of this.
You’re gonna be kind of on your own with the rest of this. Look over everything carefully.
I just changed that and it works! It as giving an error before and it might have been the variables…
The principal problem was that I did not know about the fact that Object keys are constants in JavaScript…
Thanks so much Bill I really appreciate your help ;.)