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/),
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.
### 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
- 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
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.
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
- 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_10 is the one closest to the color button.
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.
@ -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
* 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;
turn_on_leds(LED_POWER | LED_COLOR | LED_1);
if (level >= 0.15f) turn_on_leds(LED_2);
if (level >= 0.25f) turn_on_leds(LED_3);
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.config_validation as cv
from esphome.components import output
from esphome.const import CONF_ID
from esphome.const import CONF_ID, CONF_LEVEL
from esphome import automation
from .. import (
bslamp2_ns, CODEOWNERS,
@ -14,6 +14,7 @@ AUTO_LOAD = ["xiaomi_bslamp2"]
XiaomiBslamp2FrontPanelOutput = bslamp2_ns.class_(
"XiaomiBslamp2FrontPanelOutput", output.FloatOutput, cg.Component)
SetLEDsAction = bslamp2_ns.class_("SetLEDsAction", automation.Action)
SetLevelAction = bslamp2_ns.class_("SetLevelAction", automation.Action)
UpdateLEDsAction = bslamp2_ns.class_("UpdateLEDsAction", automation.Action)
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])
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 validator(value):
if isinstance(value, dict):
@ -42,13 +50,30 @@ FRONT_PANEL_SCHEMA = cv.Schema({
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(
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)
async def set_leds_to_code(config, action_id, template_arg, args):
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_;
};
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...> {
public:
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) {
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) {


+ 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.
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
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
on_progress:
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:
then:
- light.disco_on:


Loading…
Cancel
Save