ha-nest-protect
ha-nest-protect copied to clipboard
Add switch entity for Home/Away control
Description
Another feature lacking from Nest SDM is the ability to toggle home/away for the structure.
The structure.xxx
data bucket already includes the away
boolean parameter, so I believe it should be an easy addition (no protobufs required?).
Device (optional)
Structure
Additional information
No response
+1 for this.
It took a while, but I will have a look again. Can you try to execute this via https://home.nest.com/ and capture the POST request (JSON). I don't have a thermostat, so I am not able to add this.
Is this not supported in the Nest integration in core?
Hi Mick,
I did speak to Allen Porter about this a while ago, and it was because this HomeAway Sensor/Switch is not directly in the SDM API, same reason the Protects are not in the Nest Core.
I did find this switch does exist in the full blown HomeKit/Homebridge nest API (https://github.com/chrisjshull/homebridge-nest) which I understand the Protect integration is based on. If you scroll down to the Feature Options of that page you will see:
"HomeAway.AsOccupancySensorAndSwitch" - create Home/Away indicator as an OccupancySensor and a Switch
I found the Home/Away code is in the file lib/nest-homeaway-accessory.js Happy to trace the POST anyway, my thinking was if the logic below is similar to what we want to achieve?
In particular the getHome() and setHome() functions look relevant.
/**
* Created by Adrian Cable on 7/26/19.
*/
'use strict';
const { NestDeviceAccessory, Service, Characteristic } = require('./nest-device-accessory')();
const nestDeviceDescriptor = {
deviceType: 'home_away_sensor',
deviceGroup: 'home_away_sensors',
deviceDesc: 'Nest Home/Away Sensor'
};
class NestHomeAwayAccessory extends NestDeviceAccessory {
constructor(conn, log, device, structure, platform) {
super(conn, log, device, structure, platform);
if (this.platform.optionSet('HomeAway.AsOccupancySensor', this.device.serial_number, this.device.device_id) || this.platform.optionSet('HomeAway.AsOccupancySensorAndSwitch', this.device.serial_number, this.device.device_id)) {
const homeService = this.addService(Service.OccupancySensor, this.homeKitSanitize(this.device.name), 'home_occupied_sensor.' + this.device.device_id);
this.bindCharacteristic(homeService, Characteristic.OccupancyDetected, this.device.name, this.getHome);
}
if (!this.platform.optionSet('HomeAway.AsOccupancySensor', this.device.serial_number, this.device.device_id)) {
const homeService = this.addService(Service.Switch, this.homeKitSanitize(this.device.name), 'home_occupied.' + this.device.device_id);
this.bindCharacteristic(homeService, Characteristic.On, this.device.name, this.getHome, this.setHome);
}
this.updateData();
}
getHome() {
if (!this.structure.new_structure_id) {
this.conn.verbose('Warning: getting Home/Away status using REST API - may lead to issues.');
}
return !this.device.away;
}
setHome(home, callback) {
if (this.structure.new_structure_id) {
// Set using protobuf API
let cmd = {
traitLabel: 'structure_mode',
command: {
type_url: 'type.nestlabs.com/nest.trait.occupancy.StructureModeTrait.StructureModeChangeRequest',
value: {
structureMode: home ? 'STRUCTURE_MODE_HOME' : 'STRUCTURE_MODE_AWAY',
reason: 'STRUCTURE_MODE_REASON_EXPLICIT_INTENT',
userId: {
resourceId: this.structure.user_id
}
}
}
};
this.conn.protobufSendCommand([ cmd ], 'STRUCTURE_' + this.structure.new_structure_id).asCallback(callback);
} else {
// Set using REST API
this.conn.verbose('Warning: setting Home/Away status using REST API - may lead to issues.');
let val = !home ? 'away' : 'home';
this.setPropertyAsync('structure', 'away', val).asCallback(callback);
}
}
}
module.exports = function() {
Object.keys(nestDeviceDescriptor).forEach(key => NestHomeAwayAccessory[key] = NestHomeAwayAccessory.prototype[key] = nestDeviceDescriptor[key]);
return NestHomeAwayAccessory;
};
They are using Protobuf (a different protocol) for this, which we didn't implement for the Nest Protect integration (yet).
Hi Mick,
So I've traced the POST request down in Chrome Dev Tools and it seems they are not using application/json for Content-Type but instead application/x-protobuf in the actual request headers:
Request URL: https://grpc-web.production.nest.com/nestlabs.gateway.v1.ResourceApi/SendCommand Request Method: POST Status Code: 200 OK Remote Address: 34.98.67.105:443 Referrer Policy: origin Access-Control-Allow-Origin: * Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 Content-Transfer-Encoding: base64 Content-Type: application/x-protobuf.google.rpc.streambody <--------- Response Content-Type Date: Wed, 27 Dec 2023 23:46:48 GMT Server: nginx/1.11.13 Via: 1.1 google :authority: grpc-web.production.nest.com :method: POST :path: /nestlabs.gateway.v1.ResourceApi/SendCommand :scheme: https Accept: / Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.9 Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Content-Length: 219 Content-Type: application/x-protobuf <--------- Request Content-Type Origin: https://home.nest.com Referer: https://home.nest.com/ Request-Id: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Sec-Ch-Ua: "Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120" Sec-Ch-Ua-Mobile: ?0 Sec-Ch-Ua-Platform: "Windows" Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-site User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 X-Accept-Content-Transfer-Encoding: base64 X-Accept-Response-Streaming: true X-Nl-Webapp-Version: NlAppSDKVersion/9.5.3 NlSchemaVersion/2.1.20-336-g3111f722b
And the request payload looks to be the serialized class object: