Skip to content
Snippets Groups Projects
Commit e525b6e0 authored by St. John Johnson's avatar St. John Johnson
Browse files

Add brightness scale support for MQTT Lights.

Converts 0..255 values that HA expects into a device 0..SCALE value
Example:
  HA considers "hall light" at 25 brightness or 10% of 255
  Device considers "hall light" at 100 brightness or 10% of 1000

This allows our existing MQTT devices to not change their data format to be used in HA
parent dd45b5e0
No related branches found
No related tags found
No related merge requests found
......@@ -19,6 +19,7 @@ DEFAULT_QOS = 0
DEFAULT_PAYLOAD_ON = 'ON'
DEFAULT_PAYLOAD_OFF = 'OFF'
DEFAULT_OPTIMISTIC = False
DEFAULT_BRIGHTNESS_SCALE = 255
DEPENDENCIES = ['mqtt']
......@@ -44,14 +45,17 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
'on': config.get('payload_on', DEFAULT_PAYLOAD_ON),
'off': config.get('payload_off', DEFAULT_PAYLOAD_OFF)
},
config.get('optimistic', DEFAULT_OPTIMISTIC))])
config.get('optimistic', DEFAULT_OPTIMISTIC),
config.get('brightness_scale', DEFAULT_BRIGHTNESS_SCALE)
)])
class MqttLight(Light):
"""Provides a MQTT light."""
# pylint: disable=too-many-arguments,too-many-instance-attributes
def __init__(self, hass, name, topic, templates, qos, payload, optimistic):
def __init__(self, hass, name, topic, templates, qos, payload, optimistic,
brightness_scale):
self._hass = hass
self._name = name
......@@ -62,6 +66,7 @@ class MqttLight(Light):
self._optimistic_rgb = optimistic or topic["rgb_state_topic"] is None
self._optimistic_brightness = (optimistic or
topic["brightness_state_topic"] is None)
self._brightness_scale = brightness_scale
self._state = False
templates = {key: ((lambda value: value) if tpl is None else
......@@ -84,7 +89,9 @@ class MqttLight(Light):
def brightness_received(topic, payload, qos):
"""A new MQTT message for the brightness has been received."""
self._brightness = int(templates['brightness'](payload))
device_value = float(templates['brightness'](payload))
percent_bright = device_value / self._brightness_scale
self._brightness = int(percent_bright * 255)
self.update_ha_state()
if self._topic["brightness_state_topic"] is not None:
......@@ -143,6 +150,7 @@ class MqttLight(Light):
if ATTR_RGB_COLOR in kwargs and \
self._topic["rgb_command_topic"] is not None:
mqtt.publish(self._hass, self._topic["rgb_command_topic"],
"{},{},{}".format(*kwargs[ATTR_RGB_COLOR]), self._qos)
......@@ -152,9 +160,10 @@ class MqttLight(Light):
if ATTR_BRIGHTNESS in kwargs and \
self._topic["brightness_command_topic"] is not None:
percent_bright = float(kwargs[ATTR_BRIGHTNESS]) / 255
device_brightness = int(percent_bright * self._brightness_scale)
mqtt.publish(self._hass, self._topic["brightness_command_topic"],
kwargs[ATTR_BRIGHTNESS], self._qos)
device_brightness, self._qos)
if self._optimistic_brightness:
self._brightness = kwargs[ATTR_BRIGHTNESS]
......
......@@ -42,6 +42,24 @@ light:
qos: 0
payload_on: "on"
payload_off: "off"
config for RGB Version with brightness and scale:
light:
platform: mqtt
name: "Office Light RGB"
state_topic: "office/rgb1/light/status"
command_topic: "office/rgb1/light/switch"
brightness_state_topic: "office/rgb1/brightness/status"
brightness_command_topic: "office/rgb1/brightness/set"
brightness_scale: 99
rgb_state_topic: "office/rgb1/rgb/status"
rgb_command_topic: "office/rgb1/rgb/set"
rgb_scale: 99
qos: 0
payload_on: "on"
payload_off: "off"
"""
import unittest
......@@ -153,6 +171,51 @@ class TestLightMQTT(unittest.TestCase):
self.assertEqual([125, 125, 125],
light_state.attributes.get('rgb_color'))
def test_controlling_scale(self):
self.assertTrue(light.setup(self.hass, {
'light': {
'platform': 'mqtt',
'name': 'test',
'state_topic': 'test_scale/status',
'command_topic': 'test_scale/set',
'brightness_state_topic': 'test_scale/brightness/status',
'brightness_command_topic': 'test_scale/brightness/set',
'brightness_scale': '99',
'qos': 0,
'payload_on': 'on',
'payload_off': 'off'
}
}))
state = self.hass.states.get('light.test')
self.assertEqual(STATE_OFF, state.state)
self.assertIsNone(state.attributes.get('brightness'))
self.assertIsNone(state.attributes.get(ATTR_ASSUMED_STATE))
fire_mqtt_message(self.hass, 'test_scale/status', 'on')
self.hass.pool.block_till_done()
state = self.hass.states.get('light.test')
self.assertEqual(STATE_ON, state.state)
self.assertEqual(255, state.attributes.get('brightness'))
fire_mqtt_message(self.hass, 'test_scale/status', 'off')
self.hass.pool.block_till_done()
state = self.hass.states.get('light.test')
self.assertEqual(STATE_OFF, state.state)
fire_mqtt_message(self.hass, 'test_scale/status', 'on')
self.hass.pool.block_till_done()
fire_mqtt_message(self.hass, 'test_scale/brightness/status', '99')
self.hass.pool.block_till_done()
light_state = self.hass.states.get('light.test')
self.hass.pool.block_till_done()
self.assertEqual(255,
light_state.attributes['brightness'])
def test_controlling_state_via_topic_with_templates(self):
self.assertTrue(light.setup(self.hass, {
'light': {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment