Browse Source

Big change: renamed yeelight_bs2 to xiaomi_bslamp2

The reasoning behind this can be found in this issue:
https://github.com/mmakaay/esphome-yeelight_bs2/issues/7

When you are already using a previous version of the firmware,
then note that the following changes are necessary:

* Update to the latest version of the custom component code.
* Rename your folder `custom_components/yeelight_bs2` to
  `custom_components/xiaomi_bslamp2`
* Update your yaml config by changing all occurrences of `yeelight_bs2`
  into `xiaomi_bslamp2`

The links to the github repository will remain functional after
the renaming operation, so it's not required to grab a fresh clone.
pull/9/head v1.0-beta
Maurice Makaay 3 years ago
parent
commit
cf397858ba
26 changed files with 205 additions and 184 deletions
  1. +44
    -33
      README.md
  2. +5
    -5
      __init__.py
  3. +5
    -5
      binary_sensor/__init__.py
  4. +6
    -6
      binary_sensor/touch_binary_sensor.h
  5. +5
    -5
      common.h
  6. +9
    -9
      doc/FLASHING.md
  7. +20
    -15
      doc/example.yaml
  8. +0
    -0
      doc/images/screws.jpg
  9. +6
    -6
      front_panel_hal.h
  10. +7
    -7
      light/__init__.py
  11. +6
    -6
      light/automation.h
  12. +5
    -5
      light/color_instant_handler.h
  13. +9
    -5
      light/color_night_light.h
  14. +5
    -5
      light/color_off.h
  15. +4
    -4
      light/color_rgb_light.h
  16. +5
    -5
      light/color_transition_handler.h
  17. +8
    -8
      light/color_white_light.h
  18. +4
    -4
      light/gpio_outputs.h
  19. +10
    -10
      light/light_output.h
  20. +4
    -4
      light_hal.h
  21. +5
    -5
      output/__init__.py
  22. +6
    -6
      output/output.h
  23. +5
    -5
      sensor/__init__.py
  24. +7
    -6
      sensor/slider_sensor.h
  25. +7
    -7
      text_sensor/__init__.py
  26. +8
    -8
      text_sensor/light_mode_text_sensor.h

+ 44
- 33
README.md View File

@ -1,20 +1,18 @@
# esphome-yeelight_bs2
# esphome-xiaomi_bslamp2
## Warning: this code is still under development ## Warning: this code is still under development
This code might not yet be production-ready. This code might not yet be production-ready.
At this point, it is declared beta-quality.
At this point, I would call it alpha-quality. Mainly in the sense that the
interfaces that have been implemented so far might still change.
The new firmware is currently being tested and depending on the actual The new firmware is currently being tested and depending on the actual
use cases and issues that we might run into, breaking changes could still use cases and issues that we might run into, breaking changes could still
be done at some point.
occur at some point.
## Is it safe to install this firmware on my device?
As long as you keep a backup of the original Yeelight firmware, this is
quite safe :-)
## Is it safe to already install this firmware on my device?
As long as you keep a backup of the original firmware, this is quite safe :-)
I have two lamps that both are running the latest development firmware and I have two lamps that both are running the latest development firmware and
they are functioning very well. they are functioning very well.
@ -30,14 +28,20 @@ for production purposes.
## Installation ## Installation
The code must be compiled using ESPHome. Therefore, a prerequisite is that
you have ESPHome up and running in some form (command line, docker container,
web dashboard, possibly from within Home Assistant).
For information on this, please refer to the documentation on the
[ESPHome website](https://esphome.io).
Create a folder named `custom_components` in the folder where your device's Create a folder named `custom_components` in the folder where your device's
yaml configuration file is stored. Then clone the the Github repo into a yaml configuration file is stored. Then clone the the Github repo into a
subfolder `yeelight_bs2`. For example on the command line:
subfolder `xiaomi_bslamp2`. For example on the command line:
``` ```
# mkdir custom_components # mkdir custom_components
# cd custom_components # cd custom_components
# git clone https://github.com/mmakaay/esphome-yeelight_bs2 yeelight_bs2
# git clone https://github.com/mmakaay/esphome-xiaomi_bslamp2 xiaomi_bslamp2
``` ```
Your folder structure should now look like: Your folder structure should now look like:
@ -45,35 +49,39 @@ Your folder structure should now look like:
config config
├── yourdevice.yaml ├── yourdevice.yaml
├── custom_components/ ├── custom_components/
│ ├── yeelight_bs2/
│ ├── xiaomi_bslamp2/
│ . ├── README.md │ . ├── README.md
. . ├── yeelight_bs2_light_output.h
. . ├── LICENSE.md
. . . . . .
``` ```
Then add the required configuration to your device's yaml configuration file.
For an example file, take a look at [doc/example.yaml](doc/example.yaml) in
this repository.
On a Rapsbery Pi with HomeAssistant and ESPHome as a plugin, the directory On a Rapsbery Pi with HomeAssistant and ESPHome as a plugin, the directory
should be:
/config/esphome/custom_components/yeelight_bs2/
should be: `/config/esphome/custom_components/xiaomi_bslamp2/`
``` ```
config config
├── epshome
├── esphome
│ ├── yourdevice.yaml │ ├── yourdevice.yaml
│ ├── custom_components/ │ ├── custom_components/
| . ├── yeelight_bs2/
| . ├── xiaomi_bslamp2/
│ . . ├── README.md │ . . ├── README.md
. . . ├── yeelight_bs2_light_output.h
. . . ├── LICENSE.md
. . . . . . . .
``` ```
See [doc/FLASHING.md](doc/FLASHING.md) for hints for opening up the device and
flashing its firmware.
Then create the required configuration in your device's yaml configuration
file. For an example file, take a look at the example file
[doc/example.yaml](doc/example.yaml) in this repository.
After these steps you can compile your firmware `firmware.bin` file.
This firmware can then be flashed onto the device.
Like normal with ESPHome, the first time you will have to flash the
device using a serial interface. After this initial flashing operation, you
can flash new versions of the firmware using the OTA (Over The Air) method.
See [doc/FLASHING.md](doc/FLASHING.md) for hints on opening up the device and
flashing its firmware using the serial interface.
## Issue: the device keeps losing its connection to Home Assistant ## Issue: the device keeps losing its connection to Home Assistant
@ -82,34 +90,37 @@ This is not a problem with the device or the custom firmware, but a problem
in the upstream library "AsyncTCP". I did identify an issue and my pull in the upstream library "AsyncTCP". I did identify an issue and my pull
request for a fix was accepted and merged: request for a fix was accepted and merged:
https://github.com/OttoWinter/AsyncTCP/pull/4
https://github.com/OttoWinter/AsyncTCP/pull/4
If you want to try out this fix, straight from my repository, lhen create a
`libs` folder in the folder where your device's yaml configuration file is
stored, and clone the following repository into that folder:
This fix will likely be available in the next release of ESPHome
(the current version at the time of writing is 1.16.2).
If you want to try out this fix on beforehand, then create a `libs` folder
in the folder where your device's yaml configuration file is stored (e.g.
when using the Home Assistant plugin: `/config/esphome/libs/`).
Then clone the following repository into that folder:
https://github.com/mmakaay/AsyncTCP
https://github.com/OttoWinter/AsyncTCP
For example on the command line: For example on the command line:
``` ```
# cd /config/esphome
# mkdir libs # mkdir libs
# cd libs # cd libs
# git clone://github.com/mmakaay/AsyncTCP
# git clone https://github.com/OttoWinter/AsyncTCP
``` ```
Then add a pointer to this folder from within your device's yaml Then add a pointer to this folder from within your device's yaml
configuration file, using the `lib_extra_dirs` option. Provide it with the configuration file, using the `lib_extra_dirs` option. Provide it with the
absolute path to your `libs` folder. The relevant part of the config change absolute path to your `libs` folder. The relevant part of the config change
looks like this:
looks like this (matching the example from above):
```yaml ```yaml
esphome: esphome:
platformio_options: platformio_options:
lib_extra_dirs: /config/libs
lib_extra_dirs: /config/esphome/libs
``` ```
This way, the repository version of the library will override the version of This way, the repository version of the library will override the version of
the library that is bundled with ESPHome. Build the device firmware and the library that is bundled with ESPHome. Build the device firmware and
flash the device like you would normally do. flash the device like you would normally do.

+ 5
- 5
__init__.py View File

@ -13,7 +13,7 @@ from esphome.const import (
CODEOWNERS = ["@mmakaay"] CODEOWNERS = ["@mmakaay"]
CONF_HUB_ID = "yeelight_bs2_hub_id"
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"
@ -30,10 +30,10 @@ CONF_ON_BRIGHTNESS = "on_brightness"
AUTO_LOAD = ["ledc", "output", "i2c"] AUTO_LOAD = ["ledc", "output", "i2c"]
yeelight_ns = cg.esphome_ns.namespace("yeelight")
bs2_ns = yeelight_ns.namespace("bs2")
LightHAL = bs2_ns.class_("LightHAL", cg.Component)
FrontPanelHAL = bs2_ns.class_("FrontPanelHAL", cg.Component, I2CDevice)
xiaomi_ns = cg.esphome_ns.namespace("xiaomi")
bslamp2_ns = xiaomi_ns.namespace("bslamp2")
LightHAL = bslamp2_ns.class_("LightHAL", cg.Component)
FrontPanelHAL = bslamp2_ns.class_("FrontPanelHAL", cg.Component, I2CDevice)
def make_config_schema(): def make_config_schema():
schema = cv.COMPONENT_SCHEMA.extend({ schema = cv.COMPONENT_SCHEMA.extend({


+ 5
- 5
binary_sensor/__init__.py View File

@ -3,11 +3,11 @@ import esphome.config_validation as cv
from esphome.components import binary_sensor from esphome.components import binary_sensor
from esphome.const import CONF_ID from esphome.const import CONF_ID
from .. import ( from .. import (
bs2_ns, CODEOWNERS,
bslamp2_ns, CODEOWNERS,
CONF_FRONT_PANEL_HAL_ID, FrontPanelHAL CONF_FRONT_PANEL_HAL_ID, FrontPanelHAL
) )
AUTO_LOAD = ["yeelight_bs2"]
AUTO_LOAD = ["xiaomi_bslamp2"]
CONF_PART = "part" CONF_PART = "part"
@ -22,12 +22,12 @@ def validate_part(value):
value = cv.string(value) value = cv.string(value)
return cv.enum(PARTS, upper=True, space='_')(value) return cv.enum(PARTS, upper=True, space='_')(value)
YeelightBS2TouchBinarySensor = bs2_ns.class_(
"YeelightBS2TouchBinarySensor", binary_sensor.BinarySensor, cg.Component)
XiaomiBslamp2TouchBinarySensor = bslamp2_ns.class_(
"XiaomiBslamp2TouchBinarySensor", binary_sensor.BinarySensor, cg.Component)
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend(
{ {
cv.GenerateID(): cv.declare_id(YeelightBS2TouchBinarySensor),
cv.GenerateID(): cv.declare_id(XiaomiBslamp2TouchBinarySensor),
cv.GenerateID(CONF_FRONT_PANEL_HAL_ID): cv.use_id(FrontPanelHAL), cv.GenerateID(CONF_FRONT_PANEL_HAL_ID): cv.use_id(FrontPanelHAL),
cv.Optional(CONF_PART, default="ANY"): validate_part, cv.Optional(CONF_PART, default="ANY"): validate_part,
} }


+ 6
- 6
binary_sensor/touch_binary_sensor.h View File

@ -5,14 +5,14 @@
#include "esphome/components/binary_sensor/binary_sensor.h" #include "esphome/components/binary_sensor/binary_sensor.h"
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
/** /**
* This class implements a binary sensor for the touch buttons * This class implements a binary sensor for the touch buttons
* on the Yeelight Bedside Lamp 2.
* and touch slider on the front panel of the Xiaomi Mijia Bedside Lamp 2.
*/ */
class YeelightBS2TouchBinarySensor : public binary_sensor::BinarySensor, public Component {
class XiaomiBslamp2TouchBinarySensor : public binary_sensor::BinarySensor, public Component {
public: public:
void set_parent(FrontPanelHAL *front_panel) { void set_parent(FrontPanelHAL *front_panel) {
front_panel_ = front_panel; front_panel_ = front_panel;
@ -52,6 +52,6 @@ protected:
EVENT part_; EVENT part_;
}; };
} // namespace bs2
} // namespace yeelight
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome } // namespace esphome

+ 5
- 5
common.h View File

@ -1,11 +1,11 @@
#pragma once #pragma once
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
static const char *TAG = "yeelight_bs2";
static const char *TAG = "xiaomi_bslamp2";
} // namespace bs2
} // namespace yeelight
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome } // namespace esphome

+ 9
- 9
doc/FLASHING.md View File

@ -1,4 +1,4 @@
# Flashing the Yeelight Bedside Lamp 2
# Flashing the Xiaomi Mijia Bedside Lamp 2
## Tools needed ## Tools needed
@ -13,18 +13,18 @@
We have writen these instructions with care, but we will give absolutely no We have writen these instructions with care, but we will give absolutely no
warranty. Perhaps you will destroy your device and your computer. warranty. Perhaps you will destroy your device and your computer.
## Opening the Yeelight
## Opening the lamp, to expose the PCB
Remove the rubber pads from the botton of the device.
Remove the rubber pads from the botton of the lamp.
Unbolt the 4 screws which were hidden by the rubber pads. Unbolt the 4 screws which were hidden by the rubber pads.
![Photo of the screws](images/Yeelight_screws.jpg "Use an allen key or torx screw driver to remove the screws.")
![Photo of the screws](images/screws.jpg "Use an allen key or torx screw driver to remove the screws.")
Remove the bottom from the device, exposing the PCB. 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. This might take a bit of force. Just pull it up bit by bit until it pops loose.
For some good picture of disassembling this device, take a look
For some good pictures of disassembling this device, take a look
[at this blog post](https://mysku.ru/blog/china-stores/78455.html) [at this blog post](https://mysku.ru/blog/china-stores/78455.html)
It is in Russian, but the translation by Google works well and moreover, the It is in Russian, but the translation by Google works well and moreover, the
pictures are the most important thing here. If you scroll down, you will pictures are the most important thing here. If you scroll down, you will
@ -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, less than optimal candidate for powering the board during flashing. Instead,
powering the lamp using its own power supply works best. powering the lamp using its own power supply works best.
![Soldering points of a yeelight](images/Soldering_points.jpg)
![Soldering points](images/Soldering_points.jpg)
You can use some sticky tape to fixate the cables before soldering. You can use some sticky tape to fixate the cables before soldering.
@ -103,7 +103,7 @@ Here's an example on how to backup the original firmware from Linux. First,
unplug your device's power supply, then start the esptool read_flash command: unplug your device's power supply, then start the esptool read_flash command:
``` ```
python esptool.py -p /dev/ttyUSB0 read_flash 0x0 0x400000 original-yeelight-firmware.bin
python esptool.py -p /dev/ttyUSB0 read_flash 0x0 0x400000 original-firmware.bin
``` ```
/dev/ttyUSB0 is the port of the usb adaper on Linux. You can find what port /dev/ttyUSB0 is the port of the usb adaper on Linux. You can find what port
@ -125,7 +125,7 @@ flashing it back onto the device.
First, unplug your device's power supply, then start the esptool write_flash command: First, unplug your device's power supply, then start the esptool write_flash command:
``` ```
python.exe .\esptool.py --chip esp32 --port COM3 --baud 115200 write_flash 0x00 original-yeelight-firmware.bin
python.exe .\esptool.py --chip esp32 --port COM3 --baud 115200 write_flash 0x00 original-firmware.bin
``` ```
Make sure that GPIO0 is connected to GND and plug in the power supply. Make sure that GPIO0 is connected to GND and plug in the power supply.
The output of esptool should now show that it connects to the device and uploads The output of esptool should now show that it connects to the device and uploads
@ -183,7 +183,7 @@ python esptool.py --chip esp32 -p /dev/ttyUSB0 --baud 115200 --before default_r
You will find the missing tasmota boot files here: You will find the missing tasmota boot files here:
https://github.com/arendst/Tasmota/tree/firmware/firmware/tasmota32/ESP32_needed_files https://github.com/arendst/Tasmota/tree/firmware/firmware/tasmota32/ESP32_needed_files
*Note: user @tabacha was not able to use tasmota with the bedside lamp 2.*
*Note: user @tabacha was not able to use tasmota with the Bedside Lamp 2.*
(remember that the [esphome-flasher](https://github.com/esphome/esphome-flasher) (remember that the [esphome-flasher](https://github.com/esphome/esphome-flasher)
will give you a bit less of a hard-core experience during flashing) will give you a bit less of a hard-core experience during flashing)


+ 20
- 15
doc/example.yaml View File

@ -7,9 +7,8 @@ substitutions:
friendly_name: Bedside Lamp friendly_name: Bedside Lamp
transition_length: 500ms transition_length: 500ms
# Some derived identifiers for the device components.
# Derive component identifiers, based on the device name.
id_light: ${name} id_light: ${name}
id_front_panel_light: ${name}_front_panel_light
id_front_panel_output: ${name}_front_panel_output id_front_panel_output: ${name}_front_panel_output
id_power_button: ${name}_power_button id_power_button: ${name}_power_button
id_color_button: ${name}_color_button id_color_button: ${name}_color_button
@ -22,24 +21,32 @@ substitutions:
wifi: wifi:
ssid: "Your-SSID" ssid: "Your-SSID"
password: "Your-Password"
use_address: 192.168.10.12
password: "Your-WiFi-Network-Password"
# Enable fallback hotspot (for captive portal) in case wifi connection fails # Enable fallback hotspot (for captive portal) in case wifi connection fails
ap: ap:
ssid: "ESPHome $friendly_name" ssid: "ESPHome $friendly_name"
password: "bedside2021"
password: "Password-For-Connecting-To-Captive-Portal"
captive_portal: captive_portal:
api: api:
password: "Password-To-Link-HomeAssistant-To-This-Device"
ota: ota:
password: "Password-For-Flashing-This-Device-Over-The-Air"
# The log level can be raised when needed for debugging the device. For
# production, a low log level is recommended. Mainly because high volume
# log output might interfere with the API/WiFi connection stability.
# So when raising the log level, beware that you might see dropped
# connections from Home Assistant and the network log viewer.
logger: logger:
level: WARN
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Configuration specific for the Yeelight Bedside Lamp 2.
# Configuration specific for the Xiaomi Mijia Bedside Lamp 2.
# This is just an example. You can of course modify it for your own needs.
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Special platform + package are used for enabling unicore and disabling the # Special platform + package are used for enabling unicore and disabling the
@ -56,7 +63,7 @@ esphome:
light: light:
# This component controls the LED lights of the device. # This component controls the LED lights of the device.
- platform: yeelight_bs2
- platform: xiaomi_bslamp2
id: ${id_light} id: ${id_light}
name: ${friendly_name} RGBW Light name: ${friendly_name} RGBW Light
default_transition_length: ${transition_length} default_transition_length: ${transition_length}
@ -91,7 +98,7 @@ light:
# This text sensor propagates the currently active light mode. # This text sensor propagates the currently active light mode.
# The possible light modes are: "off", "rgb", "white" and "night". # The possible light modes are: "off", "rgb", "white" and "night".
text_sensor: text_sensor:
- platform: yeelight_bs2
- platform: xiaomi_bslamp2
name: ${name} Light Mode name: ${name} Light Mode
id: ${id_light_mode} id: ${id_light_mode}
@ -100,7 +107,7 @@ text_sensor:
# Other values (up to 1.0) turn on the illumination and set the level # Other values (up to 1.0) turn on the illumination and set the level
# indication to the requested level. # indication to the requested level.
output: output:
- platform: yeelight_bs2
- platform: xiaomi_bslamp2
id: ${id_front_panel_output} id: ${id_front_panel_output}
# Binary sensors can be created for handling front panel touch / release # Binary sensors can be created for handling front panel touch / release
@ -110,7 +117,7 @@ output:
binary_sensor: binary_sensor:
# When touching the power button, toggle the light. # When touching the power button, toggle the light.
# When holding the power button, turn on night light mode. # When holding the power button, turn on night light mode.
- platform: yeelight_bs2
- platform: xiaomi_bslamp2
id: ${id_power_button} id: ${id_power_button}
part: power button part: power button
on_multi_click: on_multi_click:
@ -129,12 +136,10 @@ binary_sensor:
brightness: 0.01 brightness: 0.01
# When touching the color button, set a random color. # When touching the color button, set a random color.
- platform: yeelight_bs2
- platform: xiaomi_bslamp2
id: ${id_color_button} id: ${id_color_button}
part: color button part: color button
on_multi_click:
- timing:
- ON for at most 0.8s
on_press:
then: then:
- light.turn_on: - light.turn_on:
id: ${id_light} id: ${id_light}
@ -151,7 +156,7 @@ sensor:
# Brightness 0.01 initiates the light night mode, which has already # Brightness 0.01 initiates the light night mode, which has already
# been handled above. Therefore, brightness starts from 0.02 here, # been handled above. Therefore, brightness starts from 0.02 here,
# so night mode is not triggered from the slider. # so night mode is not triggered from the slider.
- platform: yeelight_bs2
- platform: xiaomi_bslamp2
id: ${id_slider_level} id: ${id_slider_level}
range_from: 0.02 range_from: 0.02
on_value: on_value:


doc/images/Yeelight_screws.jpg → doc/images/screws.jpg View File


+ 6
- 6
front_panel_hal.h View File

@ -7,8 +7,8 @@
#include "esphome/components/i2c/i2c.h" #include "esphome/components/i2c/i2c.h"
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
static const uint8_t MSG_LEN = 7; static const uint8_t MSG_LEN = 7;
using MSG = uint8_t[7]; using MSG = uint8_t[7];
@ -73,7 +73,7 @@ static const EVENT FLAG_LEVEL_UNKNOWN = 0b0000000000;
/** /**
* This class implements a parser that translates event byte codes from the * This class implements a parser that translates event byte codes from the
* Yeelight Bedside Lamp 2 into usable events.
* Xiaomi Mijia Bedside Lamp 2 into usable events.
*/ */
class FrontPanelEventParser { class FrontPanelEventParser {
public: public:
@ -158,7 +158,7 @@ protected:
/** /**
* This is a hardware abstraction layer that communicates with with front * This is a hardware abstraction layer that communicates with with front
* panel of the Yeelight Bedside Lamp 2.
* panel of the Xiaomi Mijia Bedside Lamp 2.
* *
* It serves as a hub component for other components that implement * It serves as a hub component for other components that implement
* the actual buttons and slider components. * the actual buttons and slider components.
@ -257,6 +257,6 @@ void ICACHE_RAM_ATTR HOT FrontPanelHAL::isr(FrontPanelHAL *store) {
store->event_id_++; store->event_id_++;
} }
} // namespace bs2
} // namespace yeelight
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome } // namespace esphome

+ 7
- 7
light/__init__.py View File

@ -6,23 +6,23 @@ from esphome.const import (
CONF_RED, CONF_GREEN, CONF_BLUE, CONF_WHITE, CONF_RED, CONF_GREEN, CONF_BLUE, CONF_WHITE,
CONF_OUTPUT_ID, CONF_TRIGGER_ID, CONF_ID CONF_OUTPUT_ID, CONF_TRIGGER_ID, CONF_ID
) )
from .. import bs2_ns, CODEOWNERS, CONF_LIGHT_HAL_ID, LightHAL
from .. import bslamp2_ns, CODEOWNERS, CONF_LIGHT_HAL_ID, LightHAL
AUTO_LOAD = ["yeelight_bs2"]
AUTO_LOAD = ["xiaomi_bslamp2"]
CONF_MASTER1 = "master1" CONF_MASTER1 = "master1"
CONF_MASTER2 = "master2" CONF_MASTER2 = "master2"
CONF_ON_BRIGHTNESS = "on_brightness" CONF_ON_BRIGHTNESS = "on_brightness"
YeelightBS2LightState = bs2_ns.class_("YeelightBS2LightState", light.LightState)
YeelightBS2LightOutput = bs2_ns.class_("YeelightBS2LightOutput", light.LightOutput)
BrightnessTrigger = bs2_ns.class_("BrightnessTrigger", automation.Trigger.template())
XiaomiBslamp2LightState = bslamp2_ns.class_("XiaomiBslamp2LightState", light.LightState)
XiaomiBslamp2LightOutput = bslamp2_ns.class_("XiaomiBslamp2LightOutput", light.LightOutput)
BrightnessTrigger = bslamp2_ns.class_("BrightnessTrigger", automation.Trigger.template())
CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend( CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend(
{ {
cv.GenerateID(): cv.declare_id(YeelightBS2LightState),
cv.GenerateID(): cv.declare_id(XiaomiBslamp2LightState),
cv.GenerateID(CONF_LIGHT_HAL_ID): cv.use_id(LightHAL), cv.GenerateID(CONF_LIGHT_HAL_ID): cv.use_id(LightHAL),
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(YeelightBS2LightOutput),
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(XiaomiBslamp2LightOutput),
cv.Optional(CONF_ON_BRIGHTNESS): automation.validate_automation( cv.Optional(CONF_ON_BRIGHTNESS): automation.validate_automation(
{ {
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(BrightnessTrigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(BrightnessTrigger),


+ 6
- 6
light/automation.h View File

@ -6,12 +6,12 @@
#include "light_output.h" #include "light_output.h"
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
class BrightnessTrigger : public Trigger<float> { class BrightnessTrigger : public Trigger<float> {
public: public:
explicit BrightnessTrigger(YeelightBS2LightOutput *parent) {
explicit BrightnessTrigger(XiaomiBslamp2LightOutput *parent) {
parent->add_on_state_callback([this](light::LightColorValues values) { parent->add_on_state_callback([this](light::LightColorValues values) {
auto new_brightness = values.get_brightness(); auto new_brightness = values.get_brightness();
if (values.get_state() == 0) { if (values.get_state() == 0) {
@ -28,6 +28,6 @@ protected:
float last_brightness_ = -1.0f; float last_brightness_ = -1.0f;
}; };
} // namespace yeelight_bs2
} // namespace yeelight
} // namespace bs2
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome

+ 5
- 5
light/color_instant_handler.h View File

@ -11,8 +11,8 @@
#include "color_rgb_light.h" #include "color_rgb_light.h"
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
/** /**
* This class translates LightColorValues into GPIO duty cycles that * This class translates LightColorValues into GPIO duty cycles that
@ -57,6 +57,6 @@ protected:
GPIOOutputs *night_light_ = new ColorNightLight(); GPIOOutputs *night_light_ = new ColorNightLight();
}; };
} // namespace yeelight_bs2
} // namespace yeelight
} // namespace bs2
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome

+ 9
- 5
light/color_night_light.h View File

@ -4,8 +4,8 @@
#include "gpio_outputs.h" #include "gpio_outputs.h"
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
/** /**
* This class can handle the GPIO outputs for the night light mode. * This class can handle the GPIO outputs for the night light mode.
@ -16,6 +16,10 @@ namespace bs2 {
* confusing and made me run into issues when automating the lights. * confusing and made me run into issues when automating the lights.
* Using the lowest brightness for triggering the night light feels a lot * Using the lowest brightness for triggering the night light feels a lot
* more natural. * more natural.
*
* Note that if a switch is still the preferred way to handle the night
* light mode toggle, then this still could be implemented through the
* device's yaml configuration.
*/ */
class ColorNightLight : public GPIOOutputs { class ColorNightLight : public GPIOOutputs {
public: public:
@ -54,6 +58,6 @@ public:
} }
}; };
} // namespace yeelight_bs2
} // namespace yeelight
} // namespace bs2
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome

+ 5
- 5
light/color_off.h View File

@ -7,8 +7,8 @@
#include "gpio_outputs.h" #include "gpio_outputs.h"
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
/** /**
* This class can handle the GPIO outputs in case the light of turned off. * This class can handle the GPIO outputs in case the light of turned off.
@ -31,6 +31,6 @@ public:
} }
}; };
} // namespace yeelight_bs2
} // namespace yeelight
} // namespace bs2
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome

+ 4
- 4
light/color_rgb_light.h View File

@ -7,8 +7,8 @@
#include "gpio_outputs.h" #include "gpio_outputs.h"
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
struct RGB { struct RGB {
float red; float red;
@ -378,6 +378,6 @@ protected:
}; };
} // namespace bs2
} // namespace yeelight
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome } // namespace esphome

+ 5
- 5
light/color_transition_handler.h View File

@ -5,8 +5,8 @@
#include "color_instant_handler.h" #include "color_instant_handler.h"
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
/** /**
* This is an interface definition that is used to extend the LightState * This is an interface definition that is used to extend the LightState
@ -140,6 +140,6 @@ protected:
} }
}; };
} // namespace yeelight_bs2
} // namespace yeelight
} // namespace bs2
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome

+ 8
- 8
light/color_white_light.h View File

@ -7,18 +7,18 @@
#include "gpio_outputs.h" #include "gpio_outputs.h"
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
/** /**
* The minimum color temperature in mired. Same as supported by
* the original Yeelight firmware.
* The minimum color temperature in mired.
* Same as supported by the original firmware.
*/ */
static const int MIRED_MIN = 153; static const int MIRED_MIN = 153;
/** /**
* The maximum color temperature in mired. Same as supported by
* the original Yeelight firmware.
* The maximum color temperature in mired.
* Same as supported by the original firmware.
*/ */
static const int MIRED_MAX = 588; static const int MIRED_MAX = 588;
@ -123,6 +123,6 @@ protected:
} }
}; };
} // namespace bs2
} // namespace yeelight
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome } // namespace esphome

+ 4
- 4
light/gpio_outputs.h View File

@ -1,8 +1,8 @@
#pragma once #pragma once
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
// Light modes that can be reported by implementations of GPIOOutputs. // Light modes that can be reported by implementations of GPIOOutputs.
static const std::string LIGHT_MODE_UNKNOWN { "unknown" }; static const std::string LIGHT_MODE_UNKNOWN { "unknown" };
@ -50,6 +50,6 @@ public:
} }
}; };
} // namespace bs2
} // namespace yeelight
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome } // namespace esphome

+ 10
- 10
light/light_output.h View File

@ -7,18 +7,18 @@
#include "esphome/components/ledc/ledc_output.h" #include "esphome/components/ledc/ledc_output.h"
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
/** /**
* A LightOutput class for the Yeelight Bedside Lamp 2.
* A LightOutput class for the Xiaomi Mijia Bedside Lamp 2.
* *
* The function of this class is to translate a required light state * The function of this class is to translate a required light state
* into actual physicial GPIO output signals to drive the device's LED * into actual physicial GPIO output signals to drive the device's LED
* circuitry. It forms the glue between the physical device and the * circuitry. It forms the glue between the physical device and the
* logical light color input. * logical light color input.
*/ */
class YeelightBS2LightOutput : public Component, public light::LightOutput {
class XiaomiBslamp2LightOutput : public Component, public light::LightOutput {
public: public:
void set_parent(LightHAL *light) { light_ = light; } void set_parent(LightHAL *light) { light_ = light; }
@ -97,10 +97,10 @@ protected:
CallbackManager<void(std::string)> light_mode_callback_{}; CallbackManager<void(std::string)> light_mode_callback_{};
CallbackManager<void(light::LightColorValues)> state_callback_{}; CallbackManager<void(light::LightColorValues)> state_callback_{};
friend class YeelightBS2LightState;
friend class XiaomiBslamp2LightState;
/** /**
* Called by the YeelightBS2LightState class, to set the object that can be
* Called by the XiaomiBslamp2LightState class, to set the object that can be
* used to access the protected LightTransformer data from the LightState * used to access the protected LightTransformer data from the LightState
* object. * object.
*/ */
@ -116,10 +116,10 @@ protected:
* This class is used by the ColorTransitionHandler class to inspect if * This class is used by the ColorTransitionHandler class to inspect if
* an ongoing light color transition is active in a LightState object. * an ongoing light color transition is active in a LightState object.
*/ */
class YeelightBS2LightState : public light::LightState, public LightStateTransformerInspector
class XiaomiBslamp2LightState : public light::LightState, public LightStateTransformerInspector
{ {
public: public:
YeelightBS2LightState(const std::string &name, YeelightBS2LightOutput *output) : light::LightState(name, output) {
XiaomiBslamp2LightState(const std::string &name, XiaomiBslamp2LightOutput *output) : light::LightState(name, output) {
output->set_transformer_inspector(this); output->set_transformer_inspector(this);
} }
@ -129,6 +129,6 @@ public:
float get_progress() { return transformer_->get_progress(); } float get_progress() { return transformer_->get_progress(); }
}; };
} // namespace bs2
} // namespace yeelight
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome } // namespace esphome

+ 4
- 4
light_hal.h View File

@ -5,8 +5,8 @@
#include "esphome/components/gpio/output/gpio_binary_output.h" #include "esphome/components/gpio/output/gpio_binary_output.h"
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
class LightHAL : Component { class LightHAL : Component {
public: public:
@ -43,6 +43,6 @@ protected:
gpio::GPIOBinaryOutput *master2_; gpio::GPIOBinaryOutput *master2_;
}; };
} // namespace bs2
} // namespace yeelight
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome } // namespace esphome

+ 5
- 5
output/__init__.py View File

@ -3,18 +3,18 @@ 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 .. import ( from .. import (
bs2_ns, CODEOWNERS,
bslamp2_ns, CODEOWNERS,
CONF_FRONT_PANEL_HAL_ID, FrontPanelHAL CONF_FRONT_PANEL_HAL_ID, FrontPanelHAL
) )
AUTO_LOAD = ["yeelight_bs2"]
AUTO_LOAD = ["xiaomi_bslamp2"]
YeelightBS2FrontPanelLight = bs2_ns.class_(
"YeelightBS2FrontPanelLight", output.FloatOutput, cg.Component)
XiaomiBslamp2FrontPanelLight = bslamp2_ns.class_(
"XiaomiBslamp2FrontPanelLight", output.FloatOutput, cg.Component)
CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend(
{ {
cv.GenerateID(): cv.declare_id(YeelightBS2FrontPanelLight),
cv.GenerateID(): cv.declare_id(XiaomiBslamp2FrontPanelLight),
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)


+ 6
- 6
output/output.h View File

@ -6,14 +6,14 @@
#include "esphome/components/output/float_output.h" #include "esphome/components/output/float_output.h"
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
/** /**
* An output, used for controlling the front panel illumination and * An output, used for controlling the front panel illumination and
* brightness level indicator on the Yeelight Bedside Lamp 2 front panel.
* brightness level indicator on the Xiaomi Mijia Bedside Lamp 2 front panel.
*/ */
class YeelightBS2FrontPanelLight : public output::FloatOutput, public Component {
class XiaomiBslamp2FrontPanelLight : 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; }
@ -25,6 +25,6 @@ protected:
FrontPanelHAL *front_panel_; FrontPanelHAL *front_panel_;
}; };
} // namespace bs2
} // namespace yeelight
} // namespace bslamp2
} // namespace yxiaomi
} // namespace esphome } // namespace esphome

+ 5
- 5
sensor/__init__.py View File

@ -3,18 +3,18 @@ import esphome.config_validation as cv
from esphome.components import sensor from esphome.components import sensor
from esphome.const import CONF_ID, CONF_FORCE_UPDATE, CONF_RANGE_FROM, CONF_RANGE_TO from esphome.const import CONF_ID, CONF_FORCE_UPDATE, CONF_RANGE_FROM, CONF_RANGE_TO
from .. import ( from .. import (
bs2_ns, CODEOWNERS,
bslamp2_ns, CODEOWNERS,
CONF_FRONT_PANEL_HAL_ID, FrontPanelHAL CONF_FRONT_PANEL_HAL_ID, FrontPanelHAL
) )
AUTO_LOAD = ["yeelight_bs2"]
AUTO_LOAD = ["xiaomi_bslamp2"]
YeelightBS2SliderSensor = bs2_ns.class_(
"YeelightBS2SliderSensor", sensor.Sensor, cg.Component)
XiaomiBslamp2SliderSensor = bslamp2_ns.class_(
"XiaomiBslamp2SliderSensor", sensor.Sensor, cg.Component)
CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend( CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend(
{ {
cv.GenerateID(): cv.declare_id(YeelightBS2SliderSensor),
cv.GenerateID(): cv.declare_id(XiaomiBslamp2SliderSensor),
cv.GenerateID(CONF_FRONT_PANEL_HAL_ID): cv.use_id(FrontPanelHAL), cv.GenerateID(CONF_FRONT_PANEL_HAL_ID): cv.use_id(FrontPanelHAL),
cv.Optional(CONF_FORCE_UPDATE, default=True): cv.boolean, cv.Optional(CONF_FORCE_UPDATE, default=True): cv.boolean,
cv.Optional(CONF_RANGE_FROM, default=0.01): cv.float_, cv.Optional(CONF_RANGE_FROM, default=0.01): cv.float_,


+ 7
- 6
sensor/slider_sensor.h View File

@ -6,11 +6,12 @@
#include "esphome/components/sensor/sensor.h" #include "esphome/components/sensor/sensor.h"
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
/** /**
* A sensor for the slider on the Yeelight Bedside Lamp 2.
* A sensor for the touch slider on the front panel of the
* Xiaomi Mijia Bedside Lamp 2.
* *
* This sensor publishes the level at which the slider was touched, so it * This sensor publishes the level at which the slider was touched, so it
* can be used to implement automations. Note that it does not represent * can be used to implement automations. Note that it does not represent
@ -18,7 +19,7 @@ namespace bs2 {
* component), nor the level as displayed by the slider using the front * component), nor the level as displayed by the slider using the front
* panel light (this is implemented by the slider light component). * panel light (this is implemented by the slider light component).
*/ */
class YeelightBS2SliderSensor : public sensor::Sensor, public Component {
class XiaomiBslamp2SliderSensor : public sensor::Sensor, 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 set_range_from(float from) { range_from_ = from; } void set_range_from(float from) { range_from_ = from; }
@ -59,6 +60,6 @@ protected:
float slope_; float slope_;
}; };
} // namespace bs2
} // namespace yeelight
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome } // namespace esphome

+ 7
- 7
text_sensor/__init__.py View File

@ -2,21 +2,21 @@ import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import text_sensor from esphome.components import text_sensor
from esphome.const import CONF_ID, CONF_OUTPUT_ID from esphome.const import CONF_ID, CONF_OUTPUT_ID
from .. import bs2_ns, CODEOWNERS
from ..light import YeelightBS2LightOutput
from .. import bslamp2_ns, CODEOWNERS
from ..light import XiaomiBslamp2LightOutput
DEPENDENCIES = ["yeelight_bs2"]
DEPENDENCIES = ["xiaomi_bslamp2"]
CONF_LIGHT_ID = "light_id" CONF_LIGHT_ID = "light_id"
YeelightBS2LightModeTextSensor = bs2_ns.class_(
"YeelightBS2LightModeTextSensor", text_sensor.TextSensor, cg.Component
XiaomiBslamp2LightModeTextSensor = bslamp2_ns.class_(
"XiaomiBslamp2LightModeTextSensor", text_sensor.TextSensor, cg.Component
) )
CONFIG_SCHEMA = text_sensor.TEXT_SENSOR_SCHEMA.extend( CONFIG_SCHEMA = text_sensor.TEXT_SENSOR_SCHEMA.extend(
{ {
cv.GenerateID(): cv.declare_id(YeelightBS2LightModeTextSensor),
cv.GenerateID(CONF_OUTPUT_ID): cv.use_id(YeelightBS2LightOutput),
cv.GenerateID(): cv.declare_id(XiaomiBslamp2LightModeTextSensor),
cv.GenerateID(CONF_OUTPUT_ID): cv.use_id(XiaomiBslamp2LightOutput),
} }
).extend(cv.COMPONENT_SCHEMA) ).extend(cv.COMPONENT_SCHEMA)


+ 8
- 8
text_sensor/light_mode_text_sensor.h View File

@ -3,18 +3,18 @@
#include "esphome/components/text_sensor/text_sensor.h" #include "esphome/components/text_sensor/text_sensor.h"
namespace esphome { namespace esphome {
namespace yeelight {
namespace bs2 {
namespace xiaomi {
namespace bslamp2 {
/** /**
* A text sensor, used for propagating the active light mode on the * A text sensor, used for propagating the active light mode on the
* Yeelight Bedside Lamp 2.
* Xiaomi Mijia Bedside Lamp 2.
* *
* The possible light modes are "off", "rgb", "white" and "night". * The possible light modes are "off", "rgb", "white" and "night".
*/ */
class YeelightBS2LightModeTextSensor : public text_sensor::TextSensor, public Component {
class XiaomiBslamp2LightModeTextSensor : public text_sensor::TextSensor, public Component {
public: public:
void set_parent(YeelightBS2LightOutput *light) { light_ = light; }
void set_parent(XiaomiBslamp2LightOutput *light) { light_ = light; }
void setup() { void setup() {
light_->add_on_light_mode_callback([this](std::string light_mode) { light_->add_on_light_mode_callback([this](std::string light_mode) {
@ -26,10 +26,10 @@ public:
} }
protected: protected:
YeelightBS2LightOutput *light_;
XiaomiBslamp2LightOutput *light_;
std::string last_light_mode_ = LIGHT_MODE_UNKNOWN; std::string last_light_mode_ = LIGHT_MODE_UNKNOWN;
}; };
} // namespace bs2
} // namespace yeelight
} // namespace bslamp2
} // namespace xiaomi
} // namespace esphome } // namespace esphome

Loading…
Cancel
Save