Browse Source

Added Action output.set_leds for controlling the front panel LEDs individually.

pull/39/head
Maurice Makaay 3 years ago
parent
commit
fbc65f6c91
5 changed files with 102 additions and 23 deletions
  1. +1
    -2
      components/xiaomi_bslamp2/__init__.py
  2. +30
    -14
      components/xiaomi_bslamp2/front_panel_hal.h
  3. +31
    -4
      components/xiaomi_bslamp2/output/__init__.py
  4. +29
    -0
      components/xiaomi_bslamp2/output/automation.h
  5. +11
    -3
      components/xiaomi_bslamp2/output/output.h

+ 1
- 2
components/xiaomi_bslamp2/__init__.py View File

@ -13,7 +13,6 @@ from esphome.const import (
CODEOWNERS = ["@mmakaay"] CODEOWNERS = ["@mmakaay"]
CONF_HUB_ID = "xiaomi_bslamp2_hub_id"
CONF_RED_ID = "red_id" CONF_RED_ID = "red_id"
CONF_GREEN_ID = "green_id" CONF_GREEN_ID = "green_id"
CONF_BLUE_ID = "blue_id" CONF_BLUE_ID = "blue_id"
@ -25,8 +24,8 @@ CONF_MASTER2_ID = "master2_id"
CONF_FP_I2C_ID = "front_panel_i2c_id" CONF_FP_I2C_ID = "front_panel_i2c_id"
CONF_LIGHT_HAL_ID = "light_hal_id" CONF_LIGHT_HAL_ID = "light_hal_id"
CONF_FRONT_PANEL_HAL_ID = "front_panel_hal_id" CONF_FRONT_PANEL_HAL_ID = "front_panel_hal_id"
CONF_ON_BRIGHTNESS = "on_brightness" CONF_ON_BRIGHTNESS = "on_brightness"
CONF_LEDS = "leds"
AUTO_LOAD = ["ledc", "output", "i2c"] AUTO_LOAD = ["ledc", "output", "i2c"]


+ 30
- 14
components/xiaomi_bslamp2/front_panel_hal.h View File

@ -48,7 +48,6 @@ static const LED LED_LEVEL_10 = LED_POWER|LED_COLOR|LED_1|LED_2|LED_3|LED_4|L
// Commands for the I2C interface. // Commands for the I2C interface.
static const MSG READY_FOR_EV = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; static const MSG READY_FOR_EV = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
static const MSG SET_LEDS = {0x02, 0x03, 0x00, 0x00, 0x64, 0x00, 0x00};
using EVENT = uint16_t; using EVENT = uint16_t;
@ -233,23 +232,30 @@ class FrontPanelHAL : public Component, public i2c::I2CDevice {
} }
} }
} }
/** /**
* Enables the LEDs according to the provided input.
* Turn on one or more LEDs (leaving the state of the other LEDs intact).
* The input value is a bitwise OR-ed set of LED constants. * The input value is a bitwise OR-ed set of LED constants.
* E.g. LED_POWER|LED_1|LED2
*/
void turn_on_leds(uint16_t leds) {
set_leds_(led_state_ | leds);
}
/**
* Turn off one or more LEDs (leaving the state of the other LEDs intact).
* The input value is a bitwise OR-ed set of LED constants.
*/
void turn_off_leds(uint16_t leds) {
set_leds_(led_state_ & ~leds);
}
/**
* Updates the state of the LEDs according to the provided input.
* The input value is a bitwise OR-ed set of LED constants, representing the
* LEDs that must be turned on. All other LEDs are turned off.
*/ */
void set_leds(uint16_t leds) { void set_leds(uint16_t leds) {
MSG msg;
msg[0] = SET_LEDS[0];
msg[1] = SET_LEDS[1];
msg[2] = leds >> 8;
msg[3] = leds & 0xff;
msg[4] = SET_LEDS[4];
msg[5] = SET_LEDS[5];
msg[6] = SET_LEDS[6];
write_bytes_raw(msg, MSG_LEN);
set_leds_(leds);
} }
/** /**
@ -294,6 +300,16 @@ class FrontPanelHAL : public Component, public i2c::I2CDevice {
volatile int event_id_ = 0; volatile int event_id_ = 0;
int last_event_id_ = 0; int last_event_id_ = 0;
CallbackManager<void(EVENT)> event_callback_{}; CallbackManager<void(EVENT)> event_callback_{};
MSG led_msg_ = {0x02, 0x03, 0x00, 0x00, 0x64, 0x00, 0x00};
uint16_t led_state_ = 0;
void set_leds_(uint16_t leds) {
led_state_ = 0b0000110000000000 | leds;
led_msg_[2] = led_state_ >> 8;
led_msg_[3] = led_state_ & 0xff;
write_bytes_raw(led_msg_, MSG_LEN);
}
}; };
/** /**


+ 31
- 4
components/xiaomi_bslamp2/output/__init__.py View File

@ -2,19 +2,21 @@ 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
from esphome import automation
from .. import ( from .. import (
bslamp2_ns, CODEOWNERS, bslamp2_ns, CODEOWNERS,
CONF_FRONT_PANEL_HAL_ID, FrontPanelHAL
CONF_FRONT_PANEL_HAL_ID, FrontPanelHAL, CONF_LEDS
) )
AUTO_LOAD = ["xiaomi_bslamp2"] AUTO_LOAD = ["xiaomi_bslamp2"]
XiaomiBslamp2FrontPanelLight = bslamp2_ns.class_(
"XiaomiBslamp2FrontPanelLight", output.FloatOutput, cg.Component)
XiaomiBslamp2FrontPanelOutput = bslamp2_ns.class_(
"XiaomiBslamp2FrontPanelOutput", output.FloatOutput, cg.Component)
SetLEDsAction = bslamp2_ns.class_("SetLEDsAction", automation.Action)
CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend(
{ {
cv.GenerateID(): cv.declare_id(XiaomiBslamp2FrontPanelLight),
cv.GenerateID(): cv.declare_id(XiaomiBslamp2FrontPanelOutput),
cv.GenerateID(CONF_FRONT_PANEL_HAL_ID): cv.use_id(FrontPanelHAL), cv.GenerateID(CONF_FRONT_PANEL_HAL_ID): cv.use_id(FrontPanelHAL),
} }
).extend(cv.COMPONENT_SCHEMA) ).extend(cv.COMPONENT_SCHEMA)
@ -26,3 +28,28 @@ 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_leds_value(schema):
def validator(value):
if isinstance(value, dict):
return schema(value)
return schema({ "leds": value })
return validator
@automation.register_action(
"output.set_leds",
SetLEDsAction,
cv.Schema(
maybe_simple_leds_value(cv.Schema({
cv.GenerateID(CONF_ID): cv.use_id(XiaomiBslamp2FrontPanelOutput),
cv.Required(CONF_LEDS): cv.templatable(cv.uint16_t),
}))
)
)
async def set_leds_to_code(config, action_id, template_arg, args):
output_var = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, output_var)
template_ = await cg.templatable(config[CONF_LEDS], args, cg.uint16)
cg.add(var.set_leds(template_))
return var

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

@ -0,0 +1,29 @@
#pragma once
#include "esphome/core/automation.h"
#include "esphome/core/component.h"
#include "output.h"
#include <cmath>
namespace esphome {
namespace xiaomi {
namespace bslamp2 {
template<typename... Ts> class SetLEDsAction : public Action<Ts...> {
public:
explicit SetLEDsAction(XiaomiBslamp2FrontPanelOutput *parent) : parent_(parent) {}
TEMPLATABLE_VALUE(uint16_t, leds)
void play(Ts... x) override {
uint16_t value = this->leds_.value(x...);
parent_->set_leds(value);
}
protected:
XiaomiBslamp2FrontPanelOutput *parent_;
};
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome

+ 11
- 3
components/xiaomi_bslamp2/output/output.h View File

@ -13,11 +13,19 @@ namespace bslamp2 {
* An output, used for controlling the front panel illumination and * An output, used for controlling the front panel illumination and
* level indicator on the Xiaomi Mijia Bedside Lamp 2 front panel. * level indicator on the Xiaomi Mijia Bedside Lamp 2 front panel.
*/ */
class XiaomiBslamp2FrontPanelLight : public output::FloatOutput, public Component {
class XiaomiBslamp2FrontPanelOutput : public output::FloatOutput, public Component {
public: public:
void set_parent(FrontPanelHAL *front_panel) { front_panel_ = front_panel; }
void set_parent(FrontPanelHAL *front_panel) {
front_panel_ = front_panel;
}
void write_state(float level) { front_panel_->set_light_level(level); }
void write_state(float level) {
front_panel_->set_light_level(level);
}
void set_leds(uint16_t leds) {
front_panel_->set_leds(leds);
}
protected: protected:
FrontPanelHAL *front_panel_; FrontPanelHAL *front_panel_;


Loading…
Cancel
Save