diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9a439fc --- /dev/null +++ b/.gitignore @@ -0,0 +1,48 @@ +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + diff --git a/README.md b/README.md index 40379a7..8fa00c3 100755 --- a/README.md +++ b/README.md @@ -1,40 +1,45 @@ # homebridge-http-temperature-humidity -Supports https devices on HomeBridge Platform +A HTTP(S) temperature and humidity accessory for [Homebridge](https://github.com/nfarina/homebridge). # Installation -1. Install homebridge using: npm install -g homebridge -2. Install this plugin using: npm install -g homebridge-httptemperaturehumidity -3. Update your configuration file. See sample-config.json in this repository for a sample. +1. Install homebridge using: `npm install -g homebridge` +2. Install this plugin using: `npm install -g homebridge-http-temperature-humidity` +3. Update your configuration file. See `sample-config.json` in this repository for a sample. # Configuration +Sample configuration: -Configuration sample file: - - ``` +``` "accessories": [ - "accessories": [ - { - "accessory": "HttpTemphum", - "name": "Living Room Weather", - "url": "http://192.168.1.210/weather", - "sendimmediately": "", - "http_method": "GET" - } - ] - + { + "accessory": "HttpTemphum", + "name": "Living Room Weather", + "url": "http://192.168.1.210/weather", + "httpMethod": "GET", + "humidity": true, + "cacheExpiration": 60 + } +] ``` +Set `humidity` to false if your HTTP endpoint doesn't include a humidity reading. + +The `cacheExpiration` option specifies, in seconds, how long HTTP responses will be stored in the in-memory cache. + +--- + +Your HTTP(S) endpoint should produce JSON that looks like this: -The /weather endpoint will return a json looking like this ``` { - "temperature": 25.8, - "humidity": 38 + "temperature": 25.8, + "humidity": 38 } ``` +--- -This plugin acts as an interface between a web endpoint and homebridge only. You will still need some dedicated hardware to expose the web endpoints with the temperature and humidity information. In my case, I used a simple NodeMCU board and a DHT11 (or DHT22). [Check my other repo for the NodeMCU code](https://github.com/lucacri/nodemcu-temperature-humidity-station). +**This plugin only acts as an interface between a web endpoint and Homebridge.** You will still need some dedicated hardware to expose the web endpoints with the temperature and humidity information. In my case, I used a simple NodeMCU board and a DHT11 (or DHT22). [Check my other repo for the NodeMCU code](https://github.com/lucacri/nodemcu-temperature-humidity-station). diff --git a/index.js b/index.js index 226097e..f3d7b4b 100755 --- a/index.js +++ b/index.js @@ -1,11 +1,12 @@ var Service, Characteristic; -var request = require('sync-request'); +var request = require("superagent"); -var temperatureService; -var humidityService; -var url -var humidity = 0; -var temperature = 0; +// Require and instantiate a cache module +var cacheModule = require("cache-service-cache-module"); +var cache = new cacheModule({storage: "session", defaultExpiration: 60}); + +// Require superagent-cache-plugin and pass your cache module +var superagentCache = require("superagent-cache-plugin")(cache); module.exports = function (homebridge) { Service = homebridge.hap.Service; @@ -13,68 +14,72 @@ module.exports = function (homebridge) { homebridge.registerAccessory("homebridge-httptemperaturehumidity", "HttpTemphum", HttpTemphum); } - function HttpTemphum(log, config) { this.log = log; - // url info - this.url = config["url"]; - this.http_method = config["http_method"] || "GET"; - this.sendimmediately = config["sendimmediately"] || ""; - this.name = config["name"]; - this.manufacturer = config["manufacturer"] || "Luca Manufacturer"; - this.model = config["model"] || "Luca Model"; - this.serial = config["serial"] || "Luca Serial"; - this.humidity = config["humidity"]; + // Configuration + this.url = config["url"]; + this.httpMethod = config["httpMethod"] || "GET"; + this.name = config["name"]; + this.manufacturer = config["manufacturer"] || "Generic"; + this.model = config["model"] || "HTTP(S)"; + this.serial = config["serial"] || ""; + this.humidity = config["humidity"]; + this.lastUpdateAt = config["lastUpdateAt"] || null; + this.cacheExpiration = config["cacheExpiration"] || 60; } HttpTemphum.prototype = { - httpRequest: function (url, body, method, username, password, sendimmediately, callback) { - request({ - url: url, - body: body, - method: method, - rejectUnauthorized: false - }, - function (error, response, body) { - callback(error, response, body) - }) + getRemoteState: function(service, callback) { + request(this.httpMethod, this.url) + .set("Accept", "application/json") + .use(superagentCache) + .expiration(this.cacheExpiration) + .end(function(err, res, key) { + if (err) { + this.log(`HTTP failure (${this.url})`); + callback(err); + } else { + this.log(`HTTP success (${key})`); + + this.temperatureService.setCharacteristic( + Characteristic.CurrentTemperature, + res.body.temperature + ); + this.temperature = res.body.temperature; + + if (this.humidity !== false) { + this.humidityService.setCharacteristic( + Characteristic.CurrentRelativeHumidity, + res.body.humidity + ); + this.humidity = res.body.humidity; + } + + this.lastUpdateAt = +Date.now(); + + switch (service) { + case "temperature": + callback(null, this.temperature); + break; + case "humidity": + callback(null, this.humidity); + break; + default: + var error = new Error("Unknown service: " + service); + callback(error); + } + } + }.bind(this)); }, - getStateHumidity: function(callback){ - callback(null, this.humidity); - }, - - getState: function (callback) { - var body; - - var res = request(this.http_method, this.url, {}); - if(res.statusCode > 400){ - this.log('HTTP power function failed'); - callback(error); - } else { - this.log('HTTP power function succeeded!'); - var info = JSON.parse(res.body); - - temperatureService.setCharacteristic(Characteristic.CurrentTemperature, info.temperature); - if(this.humidity !== false) - humidityService.setCharacteristic(Characteristic.CurrentRelativeHumidity, info.humidity); - - this.log(res.body); - this.log(info); - - this.temperature = info.temperature; - if(this.humidity !== false) - this.humidity = info.humidity; - - callback(null, this.temperature); - } + getTemperatureState: function(callback) { + this.getRemoteState("temperature", callback); }, - identify: function (callback) { - this.log("Identify requested!"); - callback(); // success + getHumidityState: function(callback) { + this.getRemoteState("humidity", callback); }, getServices: function () { @@ -82,24 +87,25 @@ HttpTemphum.prototype = { informationService = new Service.AccessoryInformation(); informationService - .setCharacteristic(Characteristic.Manufacturer, this.manufacturer) - .setCharacteristic(Characteristic.Model, this.model) - .setCharacteristic(Characteristic.SerialNumber, this.serial); + .setCharacteristic(Characteristic.Manufacturer, this.manufacturer) + .setCharacteristic(Characteristic.Model, this.model) + .setCharacteristic(Characteristic.SerialNumber, this.serial); services.push(informationService); - temperatureService = new Service.TemperatureSensor(this.name); - temperatureService - .getCharacteristic(Characteristic.CurrentTemperature) - .on('get', this.getState.bind(this)); - services.push(temperatureService); - - if(this.humidity !== false){ - humidityService = new Service.HumiditySensor(this.name); - humidityService - .getCharacteristic(Characteristic.CurrentRelativeHumidity) - .setProps({minValue: -100, maxValue: 100}) - .on('get', this.getStateHumidity.bind(this)); - services.push(humidityService); + this.temperatureService = new Service.TemperatureSensor(this.name); + this.temperatureService + .getCharacteristic(Characteristic.CurrentTemperature) + .setProps({ minValue: -273, maxValue: 200 }) + .on("get", this.getTemperatureState.bind(this)); + services.push(this.temperatureService); + + if (this.humidity !== false) { + this.humidityService = new Service.HumiditySensor(this.name); + this.humidityService + .getCharacteristic(Characteristic.CurrentRelativeHumidity) + .setProps({ minValue: 0, maxValue: 200 }) + .on("get", this.getHumidityState.bind(this)); + services.push(this.humidityService); } return services; diff --git a/package.json b/package.json index f20c384..304173f 100755 --- a/package.json +++ b/package.json @@ -18,6 +18,8 @@ "url": "git://github.com/lucacri/homebridge-http-temperature-humidity.git" }, "dependencies": { - "sync-request": "^2.1.0" + "cache-service-cache-module": "^1.2.4", + "superagent": "^3.3.1", + "superagent-cache-plugin": "^1.0.0" } } diff --git a/sample-config.json b/sample-config.json index d33af52..93f9354 100755 --- a/sample-config.json +++ b/sample-config.json @@ -5,7 +5,7 @@ "port": 51826, "pin": "031-45-156" }, - + "description": "The Onion!", "platforms": [], @@ -15,8 +15,9 @@ "accessory": "HttpTemphum", "name": "Living Room Weather", "url": "http://192.168.1.210/weather", - "http_method": "GET", - "humidity": true + "httpMethod": "GET", + "humidity": true, + "cacheExpiration": 60 } ] }