From 0ae5b08a3e20658b5ee817bb86338b8758927798 Mon Sep 17 00:00:00 2001 From: murch1 <18086799+murch1@users.noreply.github.com> Date: Sun, 12 Jan 2020 08:25:03 +1000 Subject: [PATCH 1/2] Update index.js Added fan: SimpleFanAccessory (for fan only control) fanlight: SimpleFanLightAccessory (for fan controllers that also control a light) --- index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 980190b..e941041 100644 --- a/index.js +++ b/index.js @@ -14,6 +14,8 @@ const GarageDoorAccessory = require('./lib/GarageDoorAccessory'); const SimpleDimmerAccessory = require('./lib/SimpleDimmerAccessory'); const SimpleBlindsAccessory = require('./lib/SimpleBlindsAccessory'); const SimpleHeaterAccessory = require('./lib/SimpleHeaterAccessory'); +const SimpleFanAccessory = require('./lib/SimpleFanAccessory'); +const SimpleFanLightAccessory = require('./lib/SimpleFanLightAccessory'); const PLUGIN_NAME = 'homebridge-tuya-lan'; const PLATFORM_NAME = 'TuyaLan'; @@ -31,7 +33,9 @@ const CLASS_DEF = { garagedoor: GarageDoorAccessory, simpledimmer: SimpleDimmerAccessory, simpleblinds: SimpleBlindsAccessory, - simpleheater: SimpleHeaterAccessory + simpleheater: SimpleHeaterAccessory, + fan: SimpleFanAccessory, + fanlight: SimpleFanLightAccessory }; let Characteristic, PlatformAccessory, Service, Categories, UUID; From 37b72267938738be6168a26f85e20c6bf6a6ebba Mon Sep 17 00:00:00 2001 From: murch1 <18086799+murch1@users.noreply.github.com> Date: Sun, 12 Jan 2020 08:30:40 +1000 Subject: [PATCH 2/2] Added SimpleFanAccessory, SimpleFanLightAccessory Adjusted the code from SimpleHeaterAccessory.js Tested on Brilliant Wifi Ceiling Fan Controller. I initially only did the fan first, but then added in the light later. For me, controller can control the light, but I have not wired that functionality it in, as I already have Hue lighting installed and didn't want to stuff that up. --- lib/SimpleFanAccessory.js | 95 +++++++++++++++++++ lib/SimpleFanLightAccessory.js | 165 +++++++++++++++++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 lib/SimpleFanAccessory.js create mode 100644 lib/SimpleFanLightAccessory.js diff --git a/lib/SimpleFanAccessory.js b/lib/SimpleFanAccessory.js new file mode 100644 index 0000000..c0eb0ee --- /dev/null +++ b/lib/SimpleFanAccessory.js @@ -0,0 +1,95 @@ +const BaseAccessory = require('./BaseAccessory'); + +class SimpleFanAccessory extends BaseAccessory { + static getCategory(Categories) { + return Categories.FAN; + } + + constructor(...props) { + super(...props); + } + + _registerPlatformAccessory() { + const {Service} = this.hap; + + this.accessory.addService(Service.Fan, this.device.context.name); + + super._registerPlatformAccessory(); + } + + _registerCharacteristics(dps) { + const {Service, Characteristic} = this.hap; + const service = this.accessory.getService(Service.Fan); + this._checkServiceName(service, this.device.context.name); + + this.dpActive = this._getCustomDP(this.device.context.dpActive) || '1'; + this.dpRotationSpeed = this._getCustomDP(this.device.context.RotationSpeed) || '3'; + + const characteristicActive = service.getCharacteristic(Characteristic.On) + .updateValue(this._getActive(dps[this.dpActive])) + .on('get', this.getActive.bind(this)) + .on('set', this.setActive.bind(this)); + + const characteristicRotationSpeed = service.getCharacteristic(Characteristic.RotationSpeed) + .setProps({ + minValue: 0, + maxValue: 3, + minStep: 1 + }) + .updateValue(this._getSpeed(dps[this.dpRotationSpeed])) + .on('get', this.getSpeed.bind(this)) + .on('set', this.setSpeed.bind(this)); + } + +// State + getActive(callback) { + this.getState(this.dpActive, (err, dp) => { + if (err) return callback(err); + + callback(null, this._getActive(dp)); + }); + } + + _getActive(dp) { + const {Characteristic} = this.hap; + + return dp; + } + + setActive(value, callback) { + const {Characteristic} = this.hap; + + return this.setState(this.dpActive, value, callback); + + callback(); + } + +// Speed + getSpeed(callback) { + this.getState(this.dpRotationSpeed, (err, dp) => { + if (err) return callback(err); + + callback(null, this._getSpeed(dp)); + }); + } + + _getSpeed(dp) { + const {Characteristic} = this.hap; +// console.log("_getSpeed = " + dp); + return dp; + } + + setSpeed(value, callback) { + const {Characteristic} = this.hap; + if (value == 0) { + return this.setState(this.dpActive, false, callback); + } else { + return this.setState(this.dpRotationSpeed, value.toString(), callback); + } + + callback(); + } + +} + +module.exports = SimpleFanAccessory; \ No newline at end of file diff --git a/lib/SimpleFanLightAccessory.js b/lib/SimpleFanLightAccessory.js new file mode 100644 index 0000000..28e9d4f --- /dev/null +++ b/lib/SimpleFanLightAccessory.js @@ -0,0 +1,165 @@ +const BaseAccessory = require('./BaseAccessory'); + +class SimpleFanAccessory extends BaseAccessory { + static getCategory(Categories) { + return Categories.FANLIGHT; + } + + constructor(...props) { + super(...props); + } + + _registerPlatformAccessory() { + const {Service} = this.hap; + + this.accessory.addService(Service.Fan, this.device.context.name); + this.accessory.addService(Service.Lightbulb, this.device.context.name + " Light"); + + super._registerPlatformAccessory(); + } + + _registerCharacteristics(dps) { + const {Service, Characteristic} = this.hap; + const serviceFan = this.accessory.getService(Service.Fan); + const serviceLightbulb = this.accessory.getService(Service.Lightbulb); + this._checkServiceName(serviceFan, this.device.context.name); + this._checkServiceName(serviceLightbulb, this.device.context.name + " Light"); + + this.dpActive = this._getCustomDP(this.device.context.dpActive) || '1'; + this.dpRotationSpeed = this._getCustomDP(this.device.context.RotationSpeed) || '3'; + this.dpLightOn = this._getCustomDP(this.device.context.dpLightOn) || '9'; + this.dpBrightness = this._getCustomDP(this.device.context.dpBrightness) || '10'; + this.dpUseLight = this._getCustomDP(this.device.context.dpUseLight) || true; + + const characteristicActive = serviceFan.getCharacteristic(Characteristic.On) + .updateValue(this._getActive(dps[this.dpActive])) + .on('get', this.getActive.bind(this)) + .on('set', this.setActive.bind(this)); + + const characteristicRotationSpeed = serviceFan.getCharacteristic(Characteristic.RotationSpeed) + .setProps({ + minValue: 0, + maxValue: 3, + minStep: 1 + }) + .updateValue(this._getSpeed(dps[this.dpRotationSpeed])) + .on('get', this.getSpeed.bind(this)) + .on('set', this.setSpeed.bind(this)); + + if (this.dpUseLight === true) { + const characterLightOn = serviceLightbulb.getCharacteristic(Characteristic.On) + .updateValue(this._getLightOn(dps[this.dpLightOn])) + .on('get', this.getLightOn.bind(this)) + .on('set', this.setLightOn.bind(this)); + + const characteristicBrightness = serviceLightbulb.getCharacteristic(Characteristic.Brightness) + .setProps({ + minValue: 0, + maxValue: 100, + minStep: 1 + }) + .updateValue(this.convertBrightnessFromTuyaToHomeKit(dps[this.dpBrightness])) + .on('get', this.getBrightness.bind(this)) + .on('set', this.setBrightness.bind(this)); + } + } + +/*************************** FAN ***************************/ +// Fan State + getActive(callback) { + this.getState(this.dpActive, (err, dp) => { + if (err) return callback(err); + + callback(null, this._getActive(dp)); + }); + } + + _getActive(dp) { + const {Characteristic} = this.hap; + + return dp; + } + + setActive(value, callback) { + const {Characteristic} = this.hap; + + return this.setState(this.dpActive, value, callback); + + callback(); + } + +// Fan Speed + getSpeed(callback) { + this.getState(this.dpRotationSpeed, (err, dp) => { + if (err) return callback(err); + + callback(null, this._getSpeed(dp)); + }); + } + + _getSpeed(dp) { + const {Characteristic} = this.hap; +// console.log("_getSpeed = " + dp); + return dp; + } + + setSpeed(value, callback) { + const {Characteristic} = this.hap; + if (value == 0) { + return this.setState(this.dpActive, false, callback); + } else { + return this.setState(this.dpRotationSpeed, value.toString(), callback); + } + + callback(); + } + +/*************************** LIGHT ***************************/ +// Lightbulb State + getLightOn(callback) { + this.getState(this.dpLightOn, (err, dp) => { + if (err) return callback(err); + + callback(null, this._getLightOn(dp)); + }); + } + + _getLightOn(dp) { + const {Characteristic} = this.hap; + + return dp; + } + + setLightOn(value, callback) { + const {Characteristic} = this.hap; + + return this.setState(this.dpLightOn, value, callback); + + callback(); + } + +// Lightbulb Brightness + getBrightness(callback) { + this.getState(this.dpBrightness, (err, dp) => { + if (err) return callback(err); + + callback(null, this._getBrightness(dp)); + }); + } + + _getBrightness(dp) { + const {Characteristic} = this.hap; +// console.log("_getBrightness = " + dp); + return dp; + } + + setBrightness(value, callback) { + const {Characteristic} = this.hap; +// console.log("setBrightness - Raw value = " + value); + return this.setState(this.dpBrightness, value, callback); + + callback(); + } +} + +module.exports = SimpleFanAccessory; \ No newline at end of file