diff --git a/README.md b/README.md index 5796dce..4106e97 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ It is **Strongly advised that you switch to the new API** but it is not required Until an alternative is determined (like Nest Weave which hasn't been released yet or setting up a website for generating tokens specifically for HomeBridge-Nest), you will have to setup an developer account for Nest. Its a simple process and if you specify that it is for Individual, then you are auto approved (at least in my experience). -_WARNING: Switching to the new API means it will show up as brand new device. This is do to the fact that the unofficial API used a different device id and we have no way to link it to the official cloud device id. This means any configurations, alarms, scenes, etc to which the Nest was associated will have need to be updated with the new Nest device._ +_WARNING: Switching to the new API means it will show up as brand new device. This is due to the fact that the unofficial API used a different device id and we have no way to link it to the official cloud device id. This means any configurations, alarms, scenes, etc to which the Nest was associated will have need to be updated with the new Nest device._ _Note: The name of the device will change as well. It matches the name displayed in the Nest app. In my case, I originally configured the Nest app so the the "Where" of my Nest was "Hallway" and I also added a label which was "Nest", so the display was "Hallway (Nest)". To fix the name to say "Nest", you can use the Nest app and blank out the "Label" and use the custom "Where" of "Nest". Anther option to fix the name is through HomeKit. HomeKit allows you to rename Accessories and Services, but it requires an app like [Insteon+](https://itunes.apple.com/us/app/insteon+/id919270334?uo=2&at=11la2C) that has the ability to change the name._ @@ -33,9 +33,10 @@ _Note: The name of the device will change as well. It matches the name displaye 6. Then just agree to the terms and submit 7. Go to **Products** and create a new product 8. Fill in: - * **Product Name**: _HomeBridge_ + * **Product Name**: _HomeBridge_ + your name (must be unique) * **Description**: _Open source project to provide HomeKit integration_ - * **Categories**: _HomeAutomation_ + * **Categories**: _Home Automation_ + * **Users**: _Individual_ * **Support URL**: _https://github.com/kraigm/homebridge-nest_ * **Redirect URL**: _[LEAVE BLANK]_ * **Permissions (minimum)**: @@ -43,7 +44,8 @@ _Note: The name of the device will change as well. It matches the name displaye * Enable **Away** with **read/write v2** * Enable **Smoke+CO alarm** with **read v4** (if you ever might want Nest Protect) * Enable **Camera** with **read v2** (if you ever might want Nest Cam, motion detection only) -9. Now you should have a product. Now locate the **Keys** section on the right of your product's page + * Permission description: fill in anything +9. Now you should have a product. Now locate the id/secret section on the right of your product's page 10. Copy the **Product ID** to your HomeBridge config as the **clientId** in the Nest config 11. Copy the **Product Secret** to your HomeBridge config as the **clientSecret** in the Nest config 12. Navigate to the **Authorization URL** @@ -65,11 +67,11 @@ Configuration sample: { "platform": "Nest", - "token" : "c.5ABsTpo88k5yfNIxZlh...", + "token" : "token will be generated upon first run of homebridge without a token", - "clientId": "developer client id", - "clientSecret": "developer client secret.", - "code": "Pin Code", + "clientId": "developer Product ID", + "clientSecret": "developer Product Secret.", + "code": "your Pincode from Nest", "username" : "username", "password" : "password" diff --git a/index.js b/index.js index 88757a6..964b8cb 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,7 @@ var nest = require('unofficial-nest-api'); var NestConnection = require('./lib/nest-connection.js'); var inherits = require('util').inherits; +var Promise = require('bluebird'); var Service, Characteristic, Accessory, uuid, Away; var DeviceAccessory, ThermostatAccessory, ProtectAccessory, CamAccessory; @@ -83,7 +84,7 @@ var setupConnection = function(config, log) { var conn = new NestConnection(token, log); if (token) { - resolve(conn) + resolve(conn); } else { conn.auth(clientId, clientSecret, code) .then(function(token) { @@ -200,7 +201,7 @@ NestPlatform.prototype = { function subscribeDone(id, data, type) { // data if set, is also stored here: nest.lastStatus.shared[thermostatID] - if (id && type != undefined && data && (that.accessoryLookup[id] || that.accessoryLookupByStructureId[id])) { + if (id && type !== undefined && data && (that.accessoryLookup[id] || that.accessoryLookupByStructureId[id])) { that.log('Update to Device: ' + id + " type: " + type); var accessory = that.accessoryLookup[id] || that.accessoryLookupByStructureId[id]; if (accessory) { @@ -224,12 +225,12 @@ NestPlatform.prototype = { } subscribe(); - callback(foundAccessories) + callback(foundAccessories); }); } }); } -} +}; function NestThermostatAccessory(log, name, device, deviceId, initialData, structure, structureId) { // device info @@ -322,7 +323,7 @@ NestThermostatAccessory.prototype.getServices = function () { }; NestThermostatAccessory.prototype.updateData = function (data) { - if (data != undefined) { + if (data !== undefined) { this.currentData = data; } var thermostat = this.getService(Service.Thermostat); @@ -344,7 +345,7 @@ NestThermostatAccessory.prototype.getCurrentHeatingCooling = function () { var low = isRange ? this.currentData.target_temperature_low : this.currentData.target_temperature; // Add threshold - var threshold = .2; + var threshold = 0.2; high += threshold; low -= threshold; @@ -462,4 +463,4 @@ NestThermostatAccessory.prototype.setAway = function (away, callback) { this.log("Setting Away for " + this.name + " to: " + away); nest.setAway(Boolean(away), this.structureId); if (callback) callback(null, away); -} +}; diff --git a/lib/nest-connection.js b/lib/nest-connection.js index c2ec3ac..a84db55 100644 --- a/lib/nest-connection.js +++ b/lib/nest-connection.js @@ -15,7 +15,7 @@ var logPrefix = "[NestFirebase] "; function Connection(token, log) { this.token = token; this.log = function(info) { - log(logPrefix + info); + log.info(logPrefix + info); }; this.debug = function(info) { log.debug(logPrefix + info); @@ -70,7 +70,7 @@ var reauthAsync = function() { return Promise.delay(5000) .then(function() { // Attempts to reauthorize Firebase connection - self.log("Reauthorizing connection"); + self.log.warn("Reauthorizing connection"); return authAsync.call(self); }) .catch(reauthLoopAsync); @@ -103,7 +103,7 @@ Connection.prototype.subscribe = function(handler) { var self = this; return new Promise(function (resolve, reject) { if (!handler){ - reject(new Error("You must specify a handler")) + reject(new Error("You must specify a handler")); } else { var notify = resolve || handler; this.conn.on('value', function (snapshot) { @@ -112,7 +112,7 @@ Connection.prototype.subscribe = function(handler) { notify(data); notify = handler; } else { - self.log("Disconnect Detected"); + self.log.warn("Disconnect Detected"); } }); } diff --git a/lib/nest-device-accessory.js b/lib/nest-device-accessory.js index a7905d4..7f74233 100644 --- a/lib/nest-device-accessory.js +++ b/lib/nest-device-accessory.js @@ -68,10 +68,10 @@ NestDeviceAccessory.prototype.bindCharacteristic = function (service, characteri }.bind(this)) .on('change', function (change) { var disp = change.newValue; - if (format && disp != null) { + if (format && disp !== null) { disp = format(disp); } - this.log(desc + " for " + this.name + " is: " + disp); + this.log.debug(desc + " for " + this.name + " is: " + disp); }.bind(this)); if (setFunc) { actual.on('set', setFunc.bind(this)); @@ -98,7 +98,7 @@ NestDeviceAccessory.prototype.getDevicePropertyPath = function(property) { NestDeviceAccessory.prototype.updateDevicePropertyAsync = function(property, value, propertyDescription, valueDescription) { propertyDescription = propertyDescription || property; valueDescription = valueDescription || value; - this.log("Setting " + propertyDescription + " for " + this.name + " to: " + valueDescription); + this.log.debug("Setting " + propertyDescription + " for " + this.name + " to: " + valueDescription); return this.conn.update(this.getDevicePropertyPath(property), value) .return(value); }; @@ -129,7 +129,7 @@ NestDeviceAccessory.prototype.cancelAutoAway = function () { NestDeviceAccessory.prototype.setAway = function (away, callback) { var val = away ? 'away' : 'home'; - this.log("Setting Away for " + this.name + " to: " + val); + this.log.info("Setting Away for " + this.name + " to: " + val); var promise = this.conn.update(this.getStructurePropertyPath("away"), val); return promise .return(away) diff --git a/lib/nest-thermostat-accessory.js b/lib/nest-thermostat-accessory.js index 02b7c2f..40da331 100644 --- a/lib/nest-thermostat-accessory.js +++ b/lib/nest-thermostat-accessory.js @@ -2,6 +2,8 @@ * Created by kraigm on 12/15/15. */ +var Promise = require('bluebird'); +var debounce = require('lodash.debounce'); var inherits = require('util').inherits; var Accessory, Service, Characteristic, uuid; var NestDeviceAccessory = require('./nest-device-accessory')(); @@ -67,6 +69,10 @@ function NestThermostatAccessory(conn, log, device, structure) { return val + "%"; }); + thermostatService.getCharacteristic(Characteristic.TargetTemperature) + .setProps({ + minStep: 0.5 + }); bindCharacteristic(Characteristic.TargetTemperature, "Target temperature", this.getTargetTemperature, this.setTargetTemperature, formatAsDisplayTemperature); bindCharacteristic(Characteristic.TargetHeatingCoolingState, "Target heating", this.getTargetHeatingCooling, this.setTargetHeatingCooling, formatHeatingCoolingState); @@ -179,7 +185,15 @@ NestThermostatAccessory.prototype.setTargetHeatingCooling = function (targetHeat .asCallback(callback); }; -NestThermostatAccessory.prototype.setTargetTemperature = function (targetTemperature, callback) { +NestThermostatAccessory.prototype.setTargetTemperature = function(targetTemperature, callback) { + this.log('Trying to set temperature ' + targetTemperature); + this.setTargetTemperatureDebounced(targetTemperature, function() { + this.log('Temperature set to ' + targetTemperature); + }.bind(this)); + return Promise.resolve().asCallback(callback); +}; + +NestThermostatAccessory.prototype.setTargetTemperatureDebounced = debounce(function (targetTemperature, callback) { var usesFahrenheit = this.usesFahrenheit(); if (usesFahrenheit) { // Convert to Fahrenheit and round to nearest integer @@ -213,7 +227,7 @@ NestThermostatAccessory.prototype.setTargetTemperature = function (targetTempera return this.cancelAutoAway() .then(this.updateDevicePropertyAsync.bind(this, key, targetTemperature, prop + "target temperature")) .asCallback(callback); -}; +}, 5000); NestThermostatAccessory.prototype.usesFahrenheit = function () { return this.getTemperatureUnits() == Characteristic.TemperatureDisplayUnits.FAHRENHEIT; diff --git a/package.json b/package.json index f48626e..da3507a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "homebridge-nest", "description": "Nest plugin for homebridge", - "version": "1.1.2", + "version": "1.1.3", "repository": { "type": "git", "url": "git://github.com/kraigm/homebridge-nest.git" @@ -17,8 +17,9 @@ "homebridge": ">=0.2.5" }, "dependencies": { - "firebase": "^2.3.2", "bluebird": "^3.2.2", + "firebase": "^2.3.2", + "lodash.debounce": "^4.0.8", "request-promise": "^1.0.2", "unofficial-nest-api": "git+https://github.com/kraigm/unofficial_nodejs_nest.git#3cbd337adc32fab3b481659b38d86f9fcd6a9c02" }