diff --git a/README.md b/README.md index e6f2264..acaa22c 100755 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ Here's a list of the devices that are currently exposed: * **Rollershutter** - exposed as a garage door * **Fan** - on/off/speed * **Input boolean** - on/off +* **Sensors** - temperature, light and humidity sensors ### Scene Support @@ -68,7 +69,7 @@ adding it to your `config.json`. "name": "HomeAssistant", "host": "http://192.168.1.16:8123", "password": "yourapipassword", - "supported_types": ["fan", "garage_door", "input_boolean", "light", "lock", "media_player", "rollershutter", "scene", "switch"] + "supported_types": ["fan", "garage_door", "input_boolean", "light", "lock", "media_player", "rollershutter", "scene", "sensor", "switch"] } ] ``` diff --git a/accessories/sensor.js b/accessories/sensor.js new file mode 100644 index 0000000..8fa8b5f --- /dev/null +++ b/accessories/sensor.js @@ -0,0 +1,108 @@ +var Service, Characteristic, communicationError; + +module.exports = function (oService, oCharacteristic, oCommunicationError) { + Service = oService; + Characteristic = oCharacteristic; + communicationError = oCommunicationError; + + return HomeAssistantSensorFactory; +}; + +function HomeAssistantSensorFactory(log, data, client) { + if (!data.attributes) { + return null; + } + var service, characteristic, transformData; + if (data.attributes.unit_of_measurement === '°C' || data.attributes.unit_of_measurement === '°F') { + service = Service.TemperatureSensor; + characteristic = Characteristic.CurrentTemperature; + transformData = function(data) { + var value = parseFloat(data.state); + // HomeKit only works with Celsius internally + if (data.attributes.unit_of_measurement === '°F') { + value = (value - 32) / 1.8; + } + return value; + }; + } else if (data.attributes.unit_of_measurement === "%" && data.entity_id.includes("humidity")) { + service = Service.HumiditySensor; + characteristic = Characteristic.CurrentRelativeHumidity; + } else if (data.attributes.unit_of_measurement === "lux") { + service = Service.LightSensor; + characteristic = Characteristic.CurrentAmbientLightLevel; + transformData = function(data) { + return Math.max(0.0001, parseFloat(data.state)); + }; + } else { + return null; + } + + return new HomeAssistantSensor(log, data, client, service, characteristic, transformData); +} + +class HomeAssistantSensor { + constructor(log, data, client, service, characteristic, transformData) { + // device info + this.data = data; + this.entity_id = data.entity_id; + if (data.attributes && data.attributes.friendly_name) { + this.name = data.attributes.friendly_name; + }else{ + this.name = data.entity_id.split('.').pop().replace(/_/g, ' '); + } + + this.entity_type = data.entity_id.split('.')[0]; + + this.client = client; + this.log = log; + + this.service = service; + this.characteristic = characteristic; + if (transformData) { + this.transformData = transformData; + } + } + + transformData(data) { + return parseFloat(data.state); + } + + onEvent(old_state, new_state) { + this.sensorService.getCharacteristic(this.characteristic) + .setValue(this.transformData(new_state), null, 'internal'); + } + + identify(callback){ + this.log("identifying: " + this.name); + callback(); + } + + getState(callback){ + this.log("fetching state for: " + this.name); + this.client.fetchState(this.entity_id, function(data) { + if (data) { + callback(null, this.transformData(data)); + }else{ + callback(communicationError); + } + }.bind(this)); + } + + getServices() { + this.sensorService = new this.service(); + var informationService = new Service.AccessoryInformation(); + + informationService + .setCharacteristic(Characteristic.Manufacturer, "Home Assistant") + .setCharacteristic(Characteristic.Model, "Sensor") + .setCharacteristic(Characteristic.SerialNumber, "xxx"); + + this.sensorService + .getCharacteristic(this.characteristic) + .on('get', this.getState.bind(this)); + + return [informationService, this.sensorService]; + } +} + +module.exports.HomeAssistantSensorFactory = HomeAssistantSensorFactory; diff --git a/index.js b/index.js index 3acda54..0959aa8 100644 --- a/index.js +++ b/index.js @@ -12,6 +12,7 @@ var HomeAssistantGarageDoor; var HomeAssistantMediaPlayer; var HomeAssistantRollershutter; var HomeAssistantFan; +var HomeAssistantSensorFactory; module.exports = function(homebridge) { console.log("homebridge API version: " + homebridge.version); @@ -27,6 +28,7 @@ module.exports = function(homebridge) { HomeAssistantRollershutter = require('./accessories/rollershutter')(Service, Characteristic, communicationError); HomeAssistantMediaPlayer = require('./accessories/media_player')(Service, Characteristic, communicationError); HomeAssistantFan = require('./accessories/fan')(Service, Characteristic, communicationError); + HomeAssistantSensorFactory = require('./accessories/sensor')(Service, Characteristic, communicationError); homebridge.registerPlatform("homebridge-homeassistant", "HomeAssistant", HomeAssistantPlatform, false); } @@ -139,8 +141,6 @@ HomeAssistantPlatform.prototype = { setTimeout(function() { that.accessories(callback); }, 5000); return; } - // that.log(response) - // that.log(data) for (var i = 0; i < data.length; i++) { entity = data[i] @@ -186,6 +186,8 @@ HomeAssistantPlatform.prototype = { accessory = new HomeAssistantSwitch(that.log, entity, that, 'input_boolean') }else if (entity_type == 'fan'){ accessory = new HomeAssistantFan(that.log, entity, that) + }else if (entity_type == 'sensor'){ + accessory = HomeAssistantSensorFactory(that.log, entity, that) } if (accessory) { diff --git a/package.json b/package.json index 6392c85..5abe938 100755 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "url": "http://github.com/home-assistant/homebridge-homeassistant/issues" }, "engines": { - "node": ">=0.12.0", + "node": ">=4.3.2", "homebridge": ">=0.3.0" }, "dependencies": {