Skip to content

Commit

Permalink
Add lightbulb Hue, Saturation, Brightness features
Browse files Browse the repository at this point in the history
  • Loading branch information
AtomBaf committed Sep 4, 2022
1 parent 9a1920e commit 2622008
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 23 deletions.
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"private": false,
"name": "homebridge-mqtt-tasmota",
"displayName": "Homebridge MQTT Tasmota",
"version": "0.5.4",
"version": "0.6.0",
"description": "A homebridge plugin to control tasmota devices via mqtt",
"main": "src/index.js",
"scripts": {
Expand Down Expand Up @@ -35,6 +35,13 @@
"bugs": {
"url": "https://github.com/atombaf/homebridge-mqtt-tasmota/issues"
},
"files": [
"config.schema.json",
"src/**/*",
"LICENSE",
"package.json",
"README.md"
],
"author": "Fabien G",
"license": "MIT",
"dependencies": {
Expand Down
1 change: 1 addition & 0 deletions src/humidity.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class MqttTasmotaHumidityAccessory extends MqttTasmotaBaseAccessory {
.getCharacteristic(this.api.hap.Characteristic.CurrentRelativeHumidity)
.updateValue(this.currentHumidity)
this.log('Updated CurrentHumidity: %f', this.currentHumidity)
break
}
}
}
Expand Down
32 changes: 22 additions & 10 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,27 @@ var lightbulb = require('./lightbulb')


handlers = {
'blinds': blinds,
'switch': switches,
'temperature': temperature,
'humidity': humidity,
'smoke': smoke,
'doorbell': doorbell,
'fan': fan,
'lightbulb': lightbulb
'mqtt-tasmota-blinds': blinds,
'mqtt-tasmota-switch': switches,
'mqtt-tasmota-temperature': temperature,
'mqtt-tasmota-humidity': humidity,
'mqtt-tasmota-smoke': smoke,
'mqtt-tasmota-doorbell': doorbell,
'mqtt-tasmota-fan': fan,
'mqtt-tasmota-lightbulb': lightbulb
}

class MqttTasmotaAccessory {

constructor(log, config, api) {

this.type = config['type']
log('New mqtt-tasmota accessory', config.accessory)
if (config.accessory == 'mqtt-tasmota') {
this.type = 'mqtt-tasmota-' + config['type']
} else {
// deprecated handler declaration
this.type = config.accessory
log('Warning: "mqtt-tasmota-[lightbulb|switch|blinds|...]" accessory is deprecated as of v0.4.0, use "mqtt-tasmota" with "type" config instead', config.accessory)
}
this.handler = new handlers[this.type](log, config, api)
}

Expand All @@ -34,5 +40,11 @@ class MqttTasmotaAccessory {
}

module.exports = (api) => {
// normal handlers
api.registerAccessory('mqtt-tasmota', MqttTasmotaAccessory)

// deprecated handler declaration
for (var name in handlers) {
api.registerAccessory(name, MqttTasmotaAccessory)
}
}
111 changes: 99 additions & 12 deletions src/lightbulb.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,47 @@ class MqttTasmotaLightBulbAccessory extends MqttTasmotaBaseAccessory {

super(log, config, api)

// device setup
this.icon = config['icon'] || 'lightbulb'

// TASMOTA vars
this.mqttTopic = config['topic']
this.mqttIndex = config['index'] || ''
this.mqttResultTopic = config['resultTopic'] || 'stat/' + this.mqttTopic + '/RESULT'
this.mqttCommandTopic = config['commandTopic'] || 'cmnd/' + this.mqttTopic + '/POWER' + this.mqttIndex
this.mqttCommandStateTopic = config['commandStateTopic'] || 'cmnd/' + this.mqttTopic + '/STATE'
this.mqttDimmerTopic = config['dimmerTopic'] || 'cmnd/' + this.mqttTopic + '/Dimmer' + this.mqttIndex
this.mqttCommandHueTopic = config['commandHueTopic'] || 'cmnd/' + this.mqttTopic + '/hsbcolor1' + this.mqttIndex
this.mqttCommandSaturationTopic = config['commandSaturationTopic'] || 'cmnd/' + this.mqttTopic + '/hsbcolor2' + this.mqttIndex
this.mqttCommandBrightnessTopic = config['commandBrightnessTopic'] || config['commandDimmerTopic'] || 'cmnd/' + this.mqttTopic + '/Dimmer' + this.mqttIndex
this.mqttTeleTopic = config['teleTopic'] || 'tele/' + this.mqttTopic + '/STATE'

// STATE vars
this.currentPower = 'OFF'; // last known power (OFF)
this.currentBrightness = 0; // last known brightness (0)
this.currentHue = 0; // last known hue (0)
this.currentSaturation = 0; // last known saturation (0)
this.currentBrightness = 100; // last known brightness (100)

this.mqttClient.subscribe(this.mqttResultTopic)
this.mqttClient.subscribe(this.mqttTeleTopic)

// register the service and provide the callback functions
this.service = new this.api.hap.Service.Lightbulb(this.name)
switch (this.icon) {
case 'switch':
this.service = new this.api.hap.Service.Switch(this.name)
break;
case 'lightbulb':
this.service = new this.api.hap.Service.Lightbulb(this.name)
break;
default:
this.log('Unknown icon type "' + this.icon + '", defaulting to "lightbulb"');
this.service = new this.api.hap.Service.Lightbulb(this.name)
}

this.service
.getCharacteristic(this.api.hap.Characteristic.On)
.on('get', this.onGetOn.bind(this))
.on('set', this.onSetOn.bind(this))

this.service
.getCharacteristic(this.api.hap.Characteristic.Brightness)
.on('get', this.onGetBrightness.bind(this))
.on('set', this.onSetBrightness.bind(this));

// send an state MQTT command to get the initial state
// send a state MQTT command to get the initial state
this.mqttClient.publish(this.mqttCommandStateTopic, null, this.mqttOptions)
}

Expand All @@ -48,6 +60,9 @@ class MqttTasmotaLightBulbAccessory extends MqttTasmotaBaseAccessory {
// JSON format is nearly the same, eg:
// - TELE : {...,"POWER":"OFF",...}
// - STAT : {"POWER":"OFF"}
// Examples:
// - STAT for LightBulb w/ HSB:
// {..., "POWER":"OFF","Dimmer":0,"Color":"000000","HSBColor":"30,67,0","Channel":[0,0,0],"Scheme":0,"Fade":"OFF","Speed":1,"LedTable":"ON",...}
// also, when using an mqttIndex > 1 the POWER property will be POWER2, POWER3, ...

message = JSON.parse(message.toString('utf-8'))
Expand All @@ -64,10 +79,57 @@ class MqttTasmotaLightBulbAccessory extends MqttTasmotaBaseAccessory {
this.log('Updated CurrentPower: %s', this.currentPower)
}

var isHue1 = message.hasOwnProperty('HSBColor') && this.mqttIndex == 1
var isHueN = message.hasOwnProperty('HSBColor' + this.mqttIndex)

if (isHue1 || isHueN) {
if (!this.service.testCharacteristic(this.api.hap.Characteristic.Hue)) {
this.log('Adding Hue Characteristic')
this.service
.getCharacteristic(this.api.hap.Characteristic.Hue)
.on('get', this.onGetHue.bind(this))
.on('set', this.onSetHue.bind(this));
}
// update CurrentHue
this.currentHue = isHue1 ? message['HSBColor'] : message['HSBColor' + this.mqttIndex]
this.currentHue = parseInt(this.currentHue.split(',')[0])
this.service
.getCharacteristic(this.api.hap.Characteristic.Hue)
.updateValue(this.currentHue)
this.log('Updated CurrentHue: %d', this.currentHue)
}

var isSaturation1 = message.hasOwnProperty('HSBColor') && this.mqttIndex == 1
var isSaturationN = message.hasOwnProperty('HSBColor' + this.mqttIndex)

if (isSaturation1 || isSaturationN) {
if (!this.service.testCharacteristic(this.api.hap.Characteristic.Saturation)) {
this.log('Adding Saturation Characteristic')
this.service
.getCharacteristic(this.api.hap.Characteristic.Saturation)
.on('get', this.onGetSaturation.bind(this))
.on('set', this.onSetSaturation.bind(this));
}
// update CurrentSaturation
this.currentSaturation = isSaturation1 ? message['HSBColor'] : message['HSBColor' + this.mqttIndex]
this.currentSaturation = parseInt(this.currentSaturation.split(',')[1])
this.service
.getCharacteristic(this.api.hap.Characteristic.Saturation)
.updateValue(this.currentSaturation)
this.log('Updated CurrentSaturation: %d', this.currentSaturation)
}

var isDimmer1 = message.hasOwnProperty('Dimmer') && this.mqttIndex == 1
var isDimmerN = message.hasOwnProperty('Dimmer' + this.mqttIndex)

if (isDimmer1 || isDimmerN) {
if (!this.service.testCharacteristic(this.api.hap.Characteristic.Brightness)) {
this.log('Adding Brightness Characteristic')
this.service
.getCharacteristic(this.api.hap.Characteristic.Brightness)
.on('get', this.onGetBrightness.bind(this))
.on('set', this.onSetBrightness.bind(this));
}
// update CurrentBrightness
this.currentBrightness = isDimmer1 ? message['Dimmer'] : message['Dimmer' + this.mqttIndex]
this.service
Expand All @@ -90,17 +152,42 @@ class MqttTasmotaLightBulbAccessory extends MqttTasmotaBaseAccessory {
callback(null)
}

onGetHue(callback) {
this.log('Requested CurrentHue: %d', this.currentHue)
callback(null, this.currentHue)
}

onSetHue(hue, callback) {
this.log('Set Hue: %d', hue)
this.currentHue = hue
this.mqttClient.publish(this.mqttCommandHueTopic, "" + this.currentHue, this.mqttOptions)
callback(null)
}

onGetSaturation(callback) {
this.log('Requested CurrentSaturation: %d', this.currentSaturation)
callback(null, this.currentSaturation)
}

onSetSaturation(saturation, callback) {
this.log('Set Saturation: %d', saturation)
this.currentSaturation = saturation
this.mqttClient.publish(this.mqttCommandSaturationTopic, "" + this.currentSaturation, this.mqttOptions)
callback(null)
}

onGetBrightness(callback) {
this.log('Requested CurrentBrightness: %d', this.currentBrightness)
callback(null, this.currentBrightness)
}

onSetBrightness(brightness, callback) {
this.log('Set Brighness: %d', brightness)
this.log('Set Brightness: %d', brightness)
this.currentBrightness = brightness
this.mqttClient.publish(this.mqttDimmerTopic, "" + this.currentBrightness, this.mqttOptions)
this.mqttClient.publish(this.mqttCommandBrightnessTopic, "" + this.currentBrightness, this.mqttOptions)
callback(null)
}

}

module.exports = MqttTasmotaLightBulbAccessory
Expand Down
1 change: 1 addition & 0 deletions src/temperature.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class MqttTasmotaTemperatureAccessory extends MqttTasmotaBaseAccessory {
.getCharacteristic(this.api.hap.Characteristic.CurrentTemperature)
.updateValue(this.currentTemperature)
this.log('Updated CurrentTemperature: %f', this.currentTemperature)
break
}
}
}
Expand Down

0 comments on commit 2622008

Please sign in to comment.