UNPKG

homebridge-http-haikuhelper

Version:

http(s) plugin for Homebridge: https://github.com/nfarina/homebridge

409 lines (361 loc) 13.2 kB
var Service, Characteristic; var request = require("request"); var pollingtoevent = require('polling-to-event'); module.exports = function(homebridge){ Service = homebridge.hap.Service; Characteristic = homebridge.hap.Characteristic; homebridge.registerAccessory("homebridge-http-haikuhelper", "Haiku", HaikuHelperAccessory); } function HttpAdvancedAccessory(log, config) { this.log = log; // url info this.on_url = config["on_url"]; this.on_body = config["on_body"]; this.off_url = config["off_url"]; this.off_body = config["off_body"]; this.lock_url = config["lock_url"]; this.lock_body = config["lock_body"]; this.unlock_url = config["unlock_url"] || this.lock_url; this.unlock_body = config["unlock_body"] || this.lock_body; this.status_url = config["status_url"]; this.brightness_url = config["brightness_url"]; this.brightnesslvl_url = config["brightnesslvl_url"]; this.http_method = config["http_method"] || "GET"; this.http_brightness_method = config["http_brightness_method"] || this.http_method; this.http_lock_method = config["http_lock_method"] || this.http_method; this.username = config["username"] || ""; this.password = config["password"] || ""; this.sendimmediately = config["sendimmediately"] || ""; this.service = config["service"] || "Switch"; this.name = config["name"]; this.brightnessHandling = config["brightnessHandling"] || "no"; this.switchHandling = config["switchHandling"] || "no"; this.state = false; this.currentlevel = 0; var that = this; // Status Polling if ((this.status_url && this.switchHandling =="realtime") || (this.service=="Smoke" || this.service=="Motion" || (this.service=="Contact" )) { var powerurl = this.status_url; var statusemitter = pollingtoevent(function(done) { that.httpRequest(powerurl, "", "GET", that.username, that.password, that.sendimmediately, function(error, response, body) { if (error) { that.log('HTTP get power function failed: %s', error.message); callback(error); } else { done(null, body); } }) }, {longpolling:true,interval:300,longpollEventName:"statuspoll"}); statusemitter.on("statuspoll", function(data) { var binaryState = parseInt(data); that.state = binaryState > 0; that.log(that.service, "received data:"+that.status_url, "state is currently", binaryState); switch (that.service) { case "Switch": if (that.switchService ) { that.switchService .getCharacteristic(Characteristic.On) .setValue(that.state); } break; case "Light": if (that.lightbulbService) { that.lightbulbService.getCharacteristic(Characteristic.On) .setValue(that.state); } break; case "Smoke": if (that.smokeService) { that.smokeService.getCharacteristic(Characteristic.SmokeDetected) .setValue(that.state); } break; case "Motion": if (that.motionService) { that.motionService.getCharacteristic(Characteristic.MotionDetected) .setValue(that.state); } break; case "Contact": if (that.contactService) { that.contactService.getCharacteristic(Characteristic.ContactOpen) .setValue(that.state); } break; } }); } // Brightness Polling if (this.brightnesslvl_url && this.brightnessHandling =="realtime") { var brightnessurl = this.brightnesslvl_url; var levelemitter = pollingtoevent(function(done) { that.httpRequest(brightnessurl , "", "GET", that.username, that.password, that.sendimmediately, function(error, response, responseBody) { if (error) { that.log('HTTP get power function failed: %s', error.message); return; } else { done(null, responseBody); } }) }, {longpolling:true,interval:2000,longpollEventName:"levelpoll"}); levelemitter.on("levelpoll", function(data) { that.currentlevel = parseInt(data); if (that.lightbulbService) { that.log(that.service, "received data:"+that.brightnesslvl_url, "level is currently", that.currentlevel); that.lightbulbService.getCharacteristic(Characteristic.Brightness) .setValue(that.currentlevel); } }); } } HttpAdvancedAccessory.prototype = { httpRequest: function(url, body, method, username, password, sendimmediately, callback) { request({ url: url, body: body, method: method, rejectUnauthorized: false, auth: { user: username, pass: password, sendImmediately: sendimmediately } }, function(error, response, body) { callback(error, response, body) }) }, getStatusState: function(callback) { if (!this.status_url) { this.log.warn("Ignoring request; No status url defined."); callback(new Error("No status url defined.")); return; } var service = this.service; var url = this.status_url; this.log("Getting" , service , "state"); this.httpRequest(url, "", "GET", this.username, this.password, this.sendimmediately, function(error, response, responseBody) { if (error) { this.log('HTTP get power function failed: %s', error.message); callback(error); } else { var binaryState = parseInt(responseBody); var powerOn = binaryState > 0; this.log(service, "state is currently", binaryState); callback(null, powerOn); } }.bind(this)); }, setPowerState: function(powerOn, callback) { var url; var body; if (!this.on_url || !this.off_url) { this.log.warn("Ignoring request; No power url defined."); callback(new Error("No power url defined.")); return; } if (powerOn) { url = this.on_url; body = this.on_body; this.log("Setting power state to on"); } else { url = this.off_url; body = this.off_body; this.log("Setting power state to off"); } this.httpRequest(url, body, this.http_method, this.username, this.password, this.sendimmediately, function(error, response, responseBody) { if (error) { this.log('HTTP set power function failed: %s', error.message); callback(error); } else { this.log('HTTP set power function succeeded!'); callback(); } }.bind(this)); }, getLockCurrentState: function(callback){ this.log("getLockCurrentState"); callback(null, 1); //Not possible with my setup }, setLockCurrentState: function(callback){ this.log("setLockCurrentState"); callback(null, 1); //Not possible with my setup }, getLockTargetState: function(callback){ this.log("getLockTargetState"); callback(null, 1); //Not possible with my setup }, setLockTargetState: function(powerOn,callback) { var url; var body; if (!this.unlock_url || !this.lock_url) { this.log.warn("Ignoring request; No Door url defined."); callback(new Error("No Door url defined.")); return; } if (powerOn) { url = this.lock_url; body = this.lock_body; this.log("Locking Door"); } else { url = this.unlock_url; body = this.unlock_body; this.log("Unlocking Door"); } this.httpRequest(url, body, this.http_method, this.username, this.password, this.sendimmediately, function(error, response, responseBody) { if (error) { this.log('HTTP Door function failed: %s', error.message); callback(error); } else { this.log('HTTP Door function succeeded!'); callback(); } }.bind(this)); }, getBrightness: function(callback) { if (!this.brightnesslvl_url) { this.log.warn("Ignoring request; No brightness level url defined."); callback(new Error("No brightness level url defined.")); return; } var url = this.brightnesslvl_url; this.log("Getting Brightness level"); this.httpRequest(url, "", "GET", this.username, this.password, this.sendimmediately, function(error, response, responseBody) { if (error) { this.log('HTTP get brightness function failed: %s', error.message); callback(error); } else { var level = parseInt(responseBody); this.log("brightness state is currently %s", level); callback(null, level); } }.bind(this)); }, setBrightness: function(level, callback) { if (!this.brightness_url) { this.log.warn("Ignoring request; No brightness url defined."); callback(new Error("No brightness url defined.")); return; } if (!this.on_url || !this.off_url) { this.log.warn("Ignoring request; No power url defined."); callback(new Error("No power url defined.")); return; } var url = this.brightness_url.replace("%b", level) this.log("Setting brightness to %s", level); this.httpRequest(url, "", this.http_brightness_method, this.username, this.password, this.sendimmediately, function(error, response, body) { if (error) { this.log('HTTP brightness function failed: %s', error); callback(error); } else { this.log('HTTP brightness function succeeded!'); callback(); } }.bind(this)); }, identify: function(callback) { this.log("Identify requested!"); callback(); // success }, getServices: function() { var that = this; var informationService = new Service.AccessoryInformation(); informationService .setCharacteristic(Characteristic.Manufacturer, "HTTP Manufacturer") .setCharacteristic(Characteristic.Model, "HTTP Model") .setCharacteristic(Characteristic.SerialNumber, "HTTP Serial Number"); switch (this.service) { case "Switch": this.switchService = new Service.Switch(this.name); switch (this.switchHandling) { case "yes": this.switchService .getCharacteristic(Characteristic.On) .on('get', this.getStatusState.bind(this)) .on('set', this.setPowerState.bind(this)); return [this.switchService]; break; case "realtime": this.switchService .getCharacteristic(Characteristic.On) .on('get', function(callback) {callback(null, that.state)}) .on('set', this.setPowerState.bind(this)); return [this.switchService]; break; default : this.switchService .getCharacteristic(Characteristic.On) .on('set', this.setPowerState.bind(this)); return [this.switchService]; break;} case "Light": this.lightbulbService = new Service.Lightbulb(this.name); switch (this.switchHandling) { case "yes" : this.lightbulbService .getCharacteristic(Characteristic.On) .on('get', this.getStatusState.bind(this)) .on('set', this.setPowerState.bind(this)); break; case "realtime": this.lightbulbService .getCharacteristic(Characteristic.On) .on('get', function(callback) {callback(null, that.state)}) .on('set', this.setPowerState.bind(this)); break; default: this.lightbulbService .getCharacteristic(Characteristic.On) .on('set', this.setPowerState.bind(this)); break; } if (this.brightnessHandling == "realtime") { this.lightbulbService .addCharacteristic(new Characteristic.Brightness()) .on('get', function(callback) {callback(null, that.currentlevel)}) .on('set', this.setBrightness.bind(this)); } else if (this.brightnessHandling == "yes") { this.lightbulbService .addCharacteristic(new Characteristic.Brightness()) .on('get', this.getBrightness.bind(this)) .on('set', this.setBrightness.bind(this)); } return [informationService, this.lightbulbService]; break; case "Door": var lockService = new Service.LockMechanism(this.name); lockService .getCharacteristic(Characteristic.LockCurrentState) .on('get', this.getLockCurrentState.bind(this)) .on('set', this.setLockCurrentState.bind(this)); lockService .getCharacteristic(Characteristic.LockTargetState) .on('get', this.getLockTargetState.bind(this)) .on('set', this.setLockTargetState.bind(this)); return [lockService]; break; case "Smoke": this.smokeService = new Service.SmokeSensor(this.name); this.switchHandling=="realtime"; this.smokeService .getCharacteristic(Characteristic.SmokeDetected) .on('get', function(callback) {callback(null, that.state)}); return [this.smokeService]; case "Motion": this.motionService = new Service.MotionSensor(this.name); this.switchHandling=="realtime"; this.motionService .getCharacteristic(Characteristic.MotionDetected) .on('get', function(callback) {callback(null, that.state)}); return [this.motionService]; case "Contact": this.contactService = new Service.ContactSensor(this.name); this.switchHandling=="realtime"; this.contactService .getCharacteristic(Characteristic.ContactOpen) .on('get', function(callback) {callback(null, that.state)}); return [this.ContactService]; break; } } };