Browse Source

Implemented front_panel.set_level action for easier control of the slider LEDs.

pull/41/head
Maurice Makaay 3 years ago
parent
commit
b27ac59168
7 changed files with 95 additions and 43 deletions
  1. +6
    -12
      CHANGELOG.md
  2. +21
    -22
      components/xiaomi_bslamp2/front_panel_hal.h
  3. +30
    -5
      components/xiaomi_bslamp2/output/__init__.py
  4. +15
    -0
      components/xiaomi_bslamp2/output/automation.h
  5. +10
    -1
      components/xiaomi_bslamp2/output/output.h
  6. +11
    -0
      doc/configuration.md
  7. +2
    -3
      example.yaml

+ 6
- 12
CHANGELOG.md View File

@ -4,27 +4,21 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Not yet released]
## [1.1.0]
**Note**: This release requires ESPHome v1.20.0 or newer. **Note**: This release requires ESPHome v1.20.0 or newer.
### Added
- Implemented support for visual feedback during the OTA update process in the
`example.yaml` file: the light becomes blue during flahsing, the brightness bar
represents the progress, on failure the light flashes red and on success the
light flashes green.
## [1.1.0-RC1]
**Note**: This release requires ESPHome v1.19.0 or newer.
### Added ### Added
- It is now possible to address the LEDs in the front panel of the device individually. - It is now possible to address the LEDs in the front panel of the device individually.
There are 12 LEDs in total: the power button, the color button and 10 LEDs that are There are 12 LEDs in total: the power button, the color button and 10 LEDs that are
used by the original firmware to represent the lamp's current brightness setting. used by the original firmware to represent the lamp's current brightness setting.
The `output` component for the lamp was updated to provide access to the individual LEDs. The `output` component for the lamp was updated to provide access to the individual LEDs.
Check out the [documentation guide](https://github.com/mmakaay/esphome-xiaomi_bslamp2/blob/main/doc/configuration.md) Check out the [documentation guide](https://github.com/mmakaay/esphome-xiaomi_bslamp2/blob/main/doc/configuration.md)
for details on how to control the individual LEDs.
for details on how to control these.
- Implemented support for visual feedback during the OTA update process in the
`example.yaml` file: the light becomes blue during flahsing, the brightness bar
represents the progress, on failure the light flashes red and on success the
light flashes green.
### Changed ### Changed
- Made it possible to use lambdas with the `preset.activate` automation. This makes it - Made it possible to use lambdas with the `preset.activate` automation. This makes it


+ 21
- 22
components/xiaomi_bslamp2/front_panel_hal.h View File

@ -22,20 +22,21 @@ using EVENT = uint16_t;
// LED_1 is the slider LED closest to the power button. // LED_1 is the slider LED closest to the power button.
// LED_10 is the one closest to the color button. // LED_10 is the one closest to the color button.
enum FrontPanelLEDs { enum FrontPanelLEDs {
LED_ALL = 16384 + 4096 + 1023,
LED_POWER = 16384,
LED_COLOR = 4096,
LED_1 = 512,
LED_2 = 256,
LED_3 = 128,
LED_4 = 64,
LED_5 = 32,
LED_6 = 16,
LED_7 = 8,
LED_8 = 4,
LED_9 = 2,
LED_10 = 1,
LED_NONE = 0,
LED_ALL = 16384 + 4096 + 1023,
LED_ALL_SLIDER = 512 + 256 + 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1,
LED_POWER = 16384,
LED_COLOR = 4096,
LED_1 = 512,
LED_2 = 256,
LED_3 = 128,
LED_4 = 64,
LED_5 = 32,
LED_6 = 16,
LED_7 = 8,
LED_8 = 4,
LED_9 = 2,
LED_10 = 1,
LED_NONE = 0,
}; };
// This I2C command is used during front panel event handling. // This I2C command is used during front panel event handling.
@ -272,20 +273,18 @@ class FrontPanelHAL : public Component, public i2c::I2CDevice {
} }
/** /**
* Sets the front panel illumination to the provided level (0.0 - 1.0).
* Sets the front panel slider illumination to the provided level,
* based on a float input (0.0 - 1.0).
* *
* This implements the behavior of the original firmware for representing * This implements the behavior of the original firmware for representing
* the lamp's brightness. * the lamp's brightness.
* *
* Level 0.0 means: turn off the front panel illumination.
* The other levels are translated to one of the available levels,
* represented by the level indicator (i.e. the illumination of the
* slider bar.) The power and color button are also turned on.
* Level 0.0 means: turn off the slider illumination.
* The other levels are translated to one of the available levels.
*/ */
void set_light_level(float level) {
turn_off_leds(LED_ALL);
void set_slider_level(float level) {
turn_off_leds(LED_ALL_SLIDER);
if (level == 0.00f) return; if (level == 0.00f) return;
turn_on_leds(LED_POWER | LED_COLOR | LED_1);
if (level >= 0.15f) turn_on_leds(LED_2); if (level >= 0.15f) turn_on_leds(LED_2);
if (level >= 0.25f) turn_on_leds(LED_3); if (level >= 0.25f) turn_on_leds(LED_3);
if (level >= 0.35f) turn_on_leds(LED_4); if (level >= 0.35f) turn_on_leds(LED_4);


+ 30
- 5
components/xiaomi_bslamp2/output/__init__.py View File

@ -1,7 +1,7 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import output from esphome.components import output
from esphome.const import CONF_ID
from esphome.const import CONF_ID, CONF_LEVEL
from esphome import automation from esphome import automation
from .. import ( from .. import (
bslamp2_ns, CODEOWNERS, bslamp2_ns, CODEOWNERS,
@ -14,6 +14,7 @@ AUTO_LOAD = ["xiaomi_bslamp2"]
XiaomiBslamp2FrontPanelOutput = bslamp2_ns.class_( XiaomiBslamp2FrontPanelOutput = bslamp2_ns.class_(
"XiaomiBslamp2FrontPanelOutput", output.FloatOutput, cg.Component) "XiaomiBslamp2FrontPanelOutput", output.FloatOutput, cg.Component)
SetLEDsAction = bslamp2_ns.class_("SetLEDsAction", automation.Action) SetLEDsAction = bslamp2_ns.class_("SetLEDsAction", automation.Action)
SetLevelAction = bslamp2_ns.class_("SetLevelAction", automation.Action)
UpdateLEDsAction = bslamp2_ns.class_("UpdateLEDsAction", automation.Action) UpdateLEDsAction = bslamp2_ns.class_("UpdateLEDsAction", automation.Action)
CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend(
@ -31,6 +32,13 @@ def to_code(config):
front_panel_hal_var = yield cg.get_variable(config[CONF_FRONT_PANEL_HAL_ID]) front_panel_hal_var = yield cg.get_variable(config[CONF_FRONT_PANEL_HAL_ID])
cg.add(var.set_parent(front_panel_hal_var)) cg.add(var.set_parent(front_panel_hal_var))
def maybe_simple_level_value(schema):
def validator(value):
if isinstance(value, dict):
return schema(value)
return schema({ "level": value })
return validator
def maybe_simple_leds_value(schema): def maybe_simple_leds_value(schema):
def validator(value): def validator(value):
if isinstance(value, dict): if isinstance(value, dict):
@ -42,13 +50,30 @@ FRONT_PANEL_SCHEMA = cv.Schema({
cv.GenerateID(CONF_ID): cv.use_id(XiaomiBslamp2FrontPanelOutput), cv.GenerateID(CONF_ID): cv.use_id(XiaomiBslamp2FrontPanelOutput),
}) })
FRONT_PANEL_LEVEL_SCHEMA = cv.Schema(
maybe_simple_level_value(FRONT_PANEL_SCHEMA.extend(
{
cv.Required(CONF_LEVEL): cv.templatable(cv.percentage),
}
))
)
FRONT_PANEL_LED_SCHEMA = cv.Schema( FRONT_PANEL_LED_SCHEMA = cv.Schema(
maybe_simple_leds_value(cv.Schema({
cv.GenerateID(CONF_ID): cv.use_id(XiaomiBslamp2FrontPanelOutput),
cv.Required(CONF_LEDS): cv.ensure_list(cv.enum(FRONT_PANEL_LED_OPTIONS, upper=True)),
}))
maybe_simple_leds_value(FRONT_PANEL_SCHEMA.extend(
{
cv.Required(CONF_LEDS): cv.ensure_list(cv.enum(FRONT_PANEL_LED_OPTIONS, upper=True)),
}
))
) )
@automation.register_action("front_panel.set_level", SetLevelAction, FRONT_PANEL_LEVEL_SCHEMA)
async def set_level_to_code(config, action_id, template_arg, args):
output_var = await cg.get_variable(config[CONF_ID])
action_var = cg.new_Pvariable(action_id, template_arg, output_var)
template_ = await cg.templatable(config[CONF_LEVEL], args, float)
cg.add(action_var.set_level(template_))
return action_var
@automation.register_action("front_panel.set_leds", SetLEDsAction, FRONT_PANEL_LED_SCHEMA) @automation.register_action("front_panel.set_leds", SetLEDsAction, FRONT_PANEL_LED_SCHEMA)
async def set_leds_to_code(config, action_id, template_arg, args): async def set_leds_to_code(config, action_id, template_arg, args):
output_var = await cg.get_variable(config[CONF_ID]) output_var = await cg.get_variable(config[CONF_ID])


+ 15
- 0
components/xiaomi_bslamp2/output/automation.h View File

@ -37,6 +37,21 @@ template<typename... Ts> class SetLEDsAction : public Action<Ts...> {
XiaomiBslamp2FrontPanelOutput *parent_; XiaomiBslamp2FrontPanelOutput *parent_;
}; };
template<typename... Ts> class SetLevelAction : public Action<Ts...> {
public:
explicit SetLevelAction(XiaomiBslamp2FrontPanelOutput *parent) : parent_(parent) {}
TEMPLATABLE_VALUE(float, level)
void play(Ts... x) override {
parent_->set_level(this->level_.value(x...));
parent_->update_leds();
}
protected:
XiaomiBslamp2FrontPanelOutput *parent_;
};
template<typename... Ts> class UpdateLEDsAction : public Action<Ts...> { template<typename... Ts> class UpdateLEDsAction : public Action<Ts...> {
public: public:
explicit UpdateLEDsAction(XiaomiBslamp2FrontPanelOutput *parent) : parent_(parent) {} explicit UpdateLEDsAction(XiaomiBslamp2FrontPanelOutput *parent) : parent_(parent) {}


+ 10
- 1
components/xiaomi_bslamp2/output/output.h View File

@ -20,7 +20,16 @@ class XiaomiBslamp2FrontPanelOutput : public output::FloatOutput, public Compone
} }
void write_state(float level) { void write_state(float level) {
front_panel_->set_light_level(level);
if (level > 0) {
turn_on_leds(LED_POWER | LED_COLOR);
set_level(level);
} else {
turn_off_leds(LED_ALL);
}
}
void set_level(float level) {
front_panel_->set_slider_level(level);
} }
void set_leds(uint16_t leds) { void set_leds(uint16_t leds) {


+ 11
- 0
doc/configuration.md View File

@ -435,6 +435,17 @@ The LEDs to affect are specified in the same wat as above for `front_panel.set_l
This action turns off the provided LEDs, and leaves the rest of the LEDs as-is. This action turns off the provided LEDs, and leaves the rest of the LEDs as-is.
The LEDs to affect are specified in the same wat as above for `front_panel.set_leds`. The LEDs to affect are specified in the same wat as above for `front_panel.set_leds`.
#### `front_panel.set_level` Action
This action works like the `output.set_level` action, but it only updates the
LEDs of the slider. The LEDs for the power and color button are left as-is.
```yaml
on_...:
then:
- front_panel.set_leds: 0.5
```
#### `front_panel.update_leds` Action #### `front_panel.update_leds` Action
The previous actions only modify the required state for the front panel LEDs. The previous actions only modify the required state for the front panel LEDs.


+ 2
- 3
example.yaml View File

@ -75,9 +75,8 @@ ota:
transition_length: 0s transition_length: 0s
on_progress: on_progress:
then: then:
- output.set_level:
id: ${id_front_panel_illumination}
level: !lambda return (x / 100.0f);
- front_panel.set_level: !lambda return (x / 100.0f);
- front_panel.update_leds:
on_end: on_end:
then: then:
- light.disco_on: - light.disco_on:


Loading…
Cancel
Save