From 57e74e9e6e0111fba9d67f6d2ae622d4a1eaf49b Mon Sep 17 00:00:00 2001 From: Maurice Makaay Date: Wed, 14 Apr 2021 00:14:05 +0200 Subject: [PATCH] Implemented a float output, that is used to control the front panel light. --- binary_sensor/binary_sensor.h | 16 +-- doc/FLASHING.md | 4 +- doc/example-full.yaml | 116 ------------------ doc/example.yaml | 71 +++++++++-- .../Soldering_points.jpg} | Bin doc/{ => images}/Yeelight_screws.jpg | Bin front_panel_hal.h | 34 ++++- output/__init__.py | 28 +++++ output/output.h | 30 +++++ sensor/sensor.h | 10 +- 10 files changed, 166 insertions(+), 143 deletions(-) delete mode 100644 doc/example-full.yaml rename doc/{Soldering_points.jpeg => images/Soldering_points.jpg} (100%) rename doc/{ => images}/Yeelight_screws.jpg (100%) create mode 100644 output/__init__.py create mode 100644 output/output.h diff --git a/binary_sensor/binary_sensor.h b/binary_sensor/binary_sensor.h index d82c7bc..61c2715 100644 --- a/binary_sensor/binary_sensor.h +++ b/binary_sensor/binary_sensor.h @@ -23,13 +23,6 @@ public: } void setup() { - ESP_LOGCONFIG(TAG, "Setting up binary_sensor ..."); - ESP_LOGCONFIG(TAG, " Part: %s (id %d)", - (part_ == 1 ? "power button" : - part_ == 2 ? "color button" : - part_ == 3 ? "slider" : "any"), - part_); - front_panel_->add_on_event_callback( [this](EVENT ev) { // Filter events by part, when requested. @@ -45,6 +38,15 @@ public: ); } + void dump_config() { + ESP_LOGCONFIG(TAG, "Front panel binary_sensor:"); + ESP_LOGCONFIG(TAG, " Part: %s (id %d)", + (part_ == 1 ? "power button" : + part_ == 2 ? "color button" : + part_ == 3 ? "slider" : "any"), + part_); + } + protected: FrontPanelHAL *front_panel_; EVENT part_; diff --git a/doc/FLASHING.md b/doc/FLASHING.md index 5fbd2de..bfb2824 100644 --- a/doc/FLASHING.md +++ b/doc/FLASHING.md @@ -19,7 +19,7 @@ Remove the rubber pads from the botton of the device. Unbolt the 4 screws which were hidden by the rubber pads. -![Photo of the screws](Yeelight_screws.jpg "Use an allen key or torx screw driver to remove the screws.") +![Photo of the screws](images/Yeelight_screws.jpg "Use an allen key or torx screw driver to remove the screws.") Remove the bottom from the device, exposing the PCB. This might take a bit of force. Just pull it up bit by bit until it pops loose. @@ -43,7 +43,7 @@ is not directly connected to the 3.3V Vin of the ESP32 chip, making it a less than optimal candidate for powering the board during flashing. Instead, powering the lamp using its own power supply works best. -![Soldering points of a yeelight](Soldering_points.jpeg) +![Soldering points of a yeelight](images/Soldering_points.jpg) You can use some sticky tape to fixate the cables before soldering. diff --git a/doc/example-full.yaml b/doc/example-full.yaml deleted file mode 100644 index fa97d96..0000000 --- a/doc/example-full.yaml +++ /dev/null @@ -1,116 +0,0 @@ -substitutions: - name: bedside_lamp - friendly_name: Bedside Lamp - transition_length: 1s - -# Use your own preferences for these components. - -wifi: - #ssid: "Your-SSID" - #password: "Your-Password" - #use_address: 192.168.10.12 - # - # Enable fallback hotspot (captive portal) in case wifi connection fails - #ap: - # ssid: "Bedside_lamp_$name" - # password: "bedside2021" - -captive_portal: -api: -ota: -logger: - -# Special platform + package are used for enabling unicore and disabling the -# efuse mac crc check. These two changes are required for the ESP32-WROOM-32D -# that is used in the Yeelight bedside lamp 2. -esphome: - name: $name - platform: ESP32 - board: esp32doit-devkit-v1 - platformio_options: - platform: espressif32@3.2.0 - platform_packages: |-4 - framework-arduinoespressif32 @ https://github.com/pauln/arduino-esp32.git#solo-no-mac-crc/1.0.6 - -# NOTE: HIGHLY OPTIONAL BLOCK -# -# This yeelight_bs2 comopnent acts as the hub for the device. Other -# components talk to the hardware via this component. Normally, you -# wouldn't need to change anything in the default implementation. You -# can even fully omit this element from the configuration. -# Only define this when you need different pin numbers or want to -# assign specific ID's to the pin components. -yeelight_bs2: - red_id: TheRedOne - red: GPIO13 - green_id: TheGreenOne - green: GPIO14 - blue_id: TheBlueOne - blue: GPIO5 - white_id: TheWhiteOne - white: GPIO12 - master1_id: TheFirstMaster - master1: GPIO33 - master2_id: TheSecondMaster - master2: GPIO4 - sda: GPIO21 - scl: GPIO19 - trigger_pin: GPIO16 - -# This component controls the light of the device. -light: - - platform: yeelight_bs2 - name: ${friendly_name} RGBW Light - default_transition_length: ${transition_length} - # You can use any effects that you like. These are just examples. - effects: - - random: - name: "Slow Random" - transition_length: 30s - update_interval: 30s - - random: - name: "Fast Random" - transition_length: 3s - update_interval: 3s - -binary_sensor: - - # When pressing the power button, turn on the light. - - platform: yeelight_bs2 - id: ${name}_power_button - part: power button - on_press: - then: - - light.toggle: ${name} - - # When holding the color button, turn on night light mode. - - platform: yeelight_bs2 - id: ${name}_color_button - part: color button - on_multi_click: - - timing: - - ON for at least 0.8s - then: - - light.turn_on: - id: ${name} - brightness: 0.01 - red: 0 - green: 1 - blue: 0 - -sensor: - - # When the slider is touched, update the brightness. - # Brightness 0.01 initiates the light night mode, which has already - # been handle above. Therefore, brightness starts from 0.02 here, - # so night mode is not triggered from the slider. - - platform: yeelight_bs2 - id: ${name}_slider_level - range_from: 0.02 - on_value: - then: - - light.turn_on: - id: ${name} - brightness: !lambda return x; - - diff --git a/doc/example.yaml b/doc/example.yaml index 3eb197f..139e235 100644 --- a/doc/example.yaml +++ b/doc/example.yaml @@ -1,28 +1,41 @@ +# -------------------------------------------------------------------------- +# A few practical configuration substitutions. +# -------------------------------------------------------------------------- + substitutions: name: bedside_lamp friendly_name: Bedside Lamp - transition_length: 1s + transition_length: 800ms +# -------------------------------------------------------------------------- # Use your own preferences for these components. +# -------------------------------------------------------------------------- wifi: - #ssid: "Your-SSID" - #password: "Your-Password" - #use_address: 192.168.10.12 - # - # Enable fallback hotspot (captive portal) in case wifi connection fails - #ap: - # ssid: "Bedside_lamp_$name" - # password: "bedside2021" + ssid: "Your-SSID" + password: "Your-Password" + use_address: 192.168.10.12 + + # Enable fallback hotspot (for captive portal) in case wifi connection fails + ap: + ssid: "ESPHome $friendly_name" + password: "bedside2021" captive_portal: + api: + ota: + logger: +# -------------------------------------------------------------------------- +# Configureation specific for the Yeelight Bedside Lamp 2. +# -------------------------------------------------------------------------- + # Special platform + package are used for enabling unicore and disabling the # efuse mac crc check. These two changes are required for the ESP32-WROOM-32D -# that is used in the Yeelight bedside lamp 2. +# chip that is used in the device. esphome: name: $name platform: ESP32 @@ -30,7 +43,7 @@ esphome: platformio_options: platform: espressif32@3.2.0 platform_packages: |-4 - framework-arduinoespressif32 @ https://github.com/pauln/arduino-esp32.git#solo-no-mac-crc/1.0.6 + framework-arduinoespressif32 @ https://github.com/pauln/arduino-esp32.git#solo-no-mac-crc/1.0.6 # This component controls the light of the device. light: @@ -48,8 +61,18 @@ light: transition_length: 3s update_interval: 3s -binary_sensor: +# This output component controls the front panel light + level. +# Value 0.0 turns off the front panel light. +# Other values (up to 1.0) turn on the light + slider light level. +output: + - platform: yeelight_bs2 + id: ${name}_front_panel_light +# Binary sensors can be created for handling front panel touch / release +# events. To specify what part of the front panel to look at, the "part" +# parameter can be set to: "any" (i.e. the default), "power button", +# "color button" or "slider". +binary_sensor: # When pressing the power button, turn on the light. - platform: yeelight_bs2 id: ${name}_power_button @@ -57,11 +80,33 @@ binary_sensor: on_press: then: - light.toggle: ${name} + # When holding the color button, turn on night light mode. + - platform: yeelight_bs2 + id: ${name}_color_button + part: color button + on_multi_click: + - timing: + - ON for at least 0.8s + then: + - light.turn_on: + id: ${name} + brightness: 0.01 + red: 0 + green: 1 + blue: 0 +# This sensor component publishes touch events for the front panel slider. +# The published value represents the level at which the slider was touched. +# By default, values range from 0.01 to 1.00 (in 20 steps). This range can +# be modified using the "range_from" and "range_to" parameters. sensor: - # When touching the slider, update the brightness. + # When the slider is touched, update the brightness. + # Brightness 0.01 initiates the light night mode, which has already + # been handle above. Therefore, brightness starts from 0.02 here, + # so night mode is not triggered from the slider. - platform: yeelight_bs2 id: ${name}_slider_level + range_from: 0.02 on_value: then: - light.turn_on: diff --git a/doc/Soldering_points.jpeg b/doc/images/Soldering_points.jpg similarity index 100% rename from doc/Soldering_points.jpeg rename to doc/images/Soldering_points.jpg diff --git a/doc/Yeelight_screws.jpg b/doc/images/Yeelight_screws.jpg similarity index 100% rename from doc/Yeelight_screws.jpg rename to doc/images/Yeelight_screws.jpg diff --git a/front_panel_hal.h b/front_panel_hal.h index 445bb89..0ef3d0f 100644 --- a/front_panel_hal.h +++ b/front_panel_hal.h @@ -13,7 +13,7 @@ namespace bs2 { static const uint8_t MSG_LEN = 7; using MSG = uint8_t[7]; -// The commands that are supported by the +// The commands that are supported by the front panel component. static const MSG READY_FOR_EV = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; static const MSG TURN_ON = { 0x02, 0x03, 0x5E, 0x00, 0x64, 0x00, 0x00 }; static const MSG TURN_OFF = { 0x02, 0x03, 0x0C, 0x00, 0x64, 0x00, 0x00 }; @@ -205,6 +205,38 @@ public: } } + /** + * Sets the front panel light to the provided level (0.0 - 1.0). + * + * Level 0.0 means: turn off the front panel light. + * The other levels are translate to one of the avialable levels, + * represented by the backlight of the slider bar. + */ + void set_light_level(float level) { + if (level == 0.0f) + write_bytes_raw(TURN_OFF, MSG_LEN); + else if (level < 0.10) + write_bytes_raw(SET_LEVEL_1, MSG_LEN); + else if (level < 0.20) + write_bytes_raw(SET_LEVEL_2, MSG_LEN); + else if (level < 0.30) + write_bytes_raw(SET_LEVEL_3, MSG_LEN); + else if (level < 0.40) + write_bytes_raw(SET_LEVEL_4, MSG_LEN); + else if (level < 0.50) + write_bytes_raw(SET_LEVEL_5, MSG_LEN); + else if (level < 0.60) + write_bytes_raw(SET_LEVEL_6, MSG_LEN); + else if (level < 0.70) + write_bytes_raw(SET_LEVEL_7, MSG_LEN); + else if (level < 0.80) + write_bytes_raw(SET_LEVEL_8, MSG_LEN); + else if (level < 0.90) + write_bytes_raw(SET_LEVEL_9, MSG_LEN); + else + write_bytes_raw(SET_LEVEL_10, MSG_LEN); + } + protected: GPIOPin *trigger_pin_; static void isr(FrontPanelHAL *store); diff --git a/output/__init__.py b/output/__init__.py new file mode 100644 index 0000000..ae464e2 --- /dev/null +++ b/output/__init__.py @@ -0,0 +1,28 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import output +from esphome.const import CONF_ID +from .. import ( + bs2_ns, CODEOWNERS, + CONF_FRONT_PANEL_HAL_ID, FrontPanelHAL +) + +AUTO_LOAD = ["yeelight_bs2"] + +YeelightBS2FrontPanelLight = bs2_ns.class_( + "YeelightBS2FrontPanelLight", output.FloatOutput, cg.Component) + +CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(YeelightBS2FrontPanelLight), + cv.GenerateID(CONF_FRONT_PANEL_HAL_ID): cv.use_id(FrontPanelHAL), + } +).extend(cv.COMPONENT_SCHEMA) + +def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + yield cg.register_component(var, config) + yield output.register_output(var, config) + + front_panel_hal_var = yield cg.get_variable(config[CONF_FRONT_PANEL_HAL_ID]) + cg.add(var.set_parent(front_panel_hal_var)) diff --git a/output/output.h b/output/output.h new file mode 100644 index 0000000..e54b92c --- /dev/null +++ b/output/output.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include "../common.h" +#include "../front_panel_hal.h" +#include "esphome/components/output/float_output.h" + +namespace esphome { +namespace yeelight { +namespace bs2 { + +/** + * An output, used for controlling the front panel light on the + * Yeelight Bedside Lamp 2 front panel. + */ +class YeelightBS2FrontPanelLight : public output::FloatOutput, public Component { +public: + void set_parent(FrontPanelHAL *front_panel) { front_panel_ = front_panel; } + + void write_state(float level) { + front_panel_->set_light_level(level); + } + +protected: + FrontPanelHAL *front_panel_; +}; + +} // namespace bs2 +} // namespace yeelight +} // namespace esphome diff --git a/sensor/sensor.h b/sensor/sensor.h index c5cfa4e..385ac66 100644 --- a/sensor/sensor.h +++ b/sensor/sensor.h @@ -25,10 +25,6 @@ public: void set_range_to(float to) { range_to_ = to; } void setup() { - ESP_LOGCONFIG(TAG, "Setting up slider sensor ..."); - ESP_LOGCONFIG(TAG, " Range from: %f", range_from_); - ESP_LOGCONFIG(TAG, " Range to: %f", range_to_); - slope_ = (range_to_ - range_from_) / 19.0f; front_panel_->add_on_event_callback( @@ -50,6 +46,12 @@ public: ); } + void dump_config() { + ESP_LOGCONFIG(TAG, "Front Panel slider sensor:"); + ESP_LOGCONFIG(TAG, " Range from: %f", range_from_); + ESP_LOGCONFIG(TAG, " Range to: %f", range_to_); + } + protected: FrontPanelHAL *front_panel_; float range_from_;