Custom firmware ESPHome-Xiaomi_bslamp2

Update: We have issued an alert for the local control removal and issued a statement via Twitter. I linked our Twitter thread to this thread and thanked you @mmakaay, hope that’s okay :slightly_smiling_face:



1 Like

Of course it is okay, @robbiet480
Thanks for the shoutout :smiley: !

2 Likes

Great News @robbiet480! You definitely put Xiaomi and Yeelight in the spotlight now :grin: And @mmakaay deserves all the credit! :+1:t2::partying_face:

While playing with the original firmware, I found another good reason for using custom firmware instead. The LAN mode apparently has a requests/minute limit (also mentioned on the Yeelight integration page). When doing a lot of requests (for example when transitioning from one color to the other), this limit is quickly reached and the light will show up as disconnected. At that point, the Home-Assistant logs will show “client quota exceeded”.

Ah THAT’s why I struggled with it, while playing around! Became unavailable out of the blue.

One question, in the default scenes in the Yeelight app, there is a Night mode. I’ve never managed to set the same low light level manually, as when I use the predefined Night mode. Is this possible with your custom code?

That’s why someone came up with the “Music Mode” I think. This tricks the lamp to accept more requests.

Edit; But good riddance! Not a clean way of handling things :+1:t2:

Yes, my plan for night mode is to turn that on when using brightness level 1.
I am working on three distinct lighting modes therefore:

  • RGB (brightness 2 - 255)
  • Night light (brightness 1)
  • White light (using temperature instead of RGB settings)

The Yeelight integration does provide a switch entity for the night light mode BTW. I thought about copying that behavior, but frankly, I do not like this method at all. It provides me with two light switches for the same light and from usability and automation perspectives, I always found it challenging to work with. Therefore I went for the brightness==1 -> night light mode logic.

If somebody does want two switches, then it can of course still be done, by implementing those in the ESPHome configuration. I am writing a light output here, so that can be hooked up to other entities in any way you like.

1 Like

Awesome, I agree with your logic :slight_smile:

1 Like

First things first, thank you for doing this. I think a lot of geeks want to use this. Second, I agree with your arguments/statements, (whatever you want to call them), I like the idea of night mode when brightness is set to 1. Hopefully it will work when you control the light manually.
Please don’t include the switch like the integration. It is very confusing.

1 Like

Ahhhhh… that was fun. After doing a ton of measurements and wondering what was going on with them, I turned around my board and found the culprit.

The green lead popped off the ESP32 pin :laughing:
A should have been connected at B! That explains a lot.

There! Cringeworthy, but more gloop will help (the duct tape was too large for this one)

1 Like

WIth the green output connected back to the board, I did a lot of new RGB measurements. I went ahead on doing this, because the simple implementation (that did already look quite good) does show some irritating flaws at a few spots when transitioning from color to color.
For example red to purple shows red, then quickly light purple, then red again, which then goes towards purple. We no like, so started an effort to get more detailed insight in the outputs for RGB.

My approach for measuring is to use the RGB color circle (as used by Home Assistant) and measure all around this circle at different distances from the middle white point. I numbered the rings from 1 to 7, outward to inward. I measured from red to blue to green and back to red (so rotating anti-clockwise along the ring).

This yielded some interesting results, that tell me that RGB is going to need more code than I envisioned. Check out these beauties:

afbeelding

From left to right is the transitioning from red to blue to green and back to red.
As you can see, these aren’t nice smooth lines that tranlate into clean functions.

The above measurements were done at 100% brightness. I also measured at 1% brightness, which resulted in this output:

afbeelding

That is a very compressed version of the 100% version. The good news here is that I also measured at 50% and that I found that I could generate the same graphs by averaging the 100% and 1% results. So the brightness scaling is linear (as expected, since I’ve seen that all over the place so far).

I also did measurements along at what I called “the 4th ring”. This is ring number 4 from the outside inwards (the preveious measurements were therefore for the 1st ring). At 100% brightness, this showed:

afbeelding

The output is a bit like the 1st ring output, but the shape of the graphs is not a plain scaled version of those for the 1ste ring.
I also measured the 7th ring. This is the small inner right that is right around the middle white point. The results for this ring are:

afbeelding

Now look at that! A whole different look from the earlier graphs.

Based on this, it is clear that computing the RGB output values might not easily be some with some straight forward formulas. I will continue with measuring values on the other rings, hoping that this might reveal some logic that can be used to compute required RGB levels.

If no logic is revealed, then I will simply go for implementing the required data tables to support this.

1 Like

Mmakaay’s seven rings of RGB! (Dante would have laughed…) Peculiar how driving LEDs seems to work, and this gives me new insight to why colours is a bit off in certain products. I can see that you have more than enough to do right now, but did you ever get the second I2C bus to talk? If this is an eeprom, as mentioned earlier, it must be some kind of static memory since it isn’t especially “chatty” during operation of the lamp.

I have not yet tried to talk to the second I2C bus, mainly because I currently don’t have a use for it. Possibly it can be used for storing light presets or so, which can be made operational independently from a connection to Home Assistant through use of the front panel use.
Once I get the core functionality working, I will solder some more wires to the original lamp to see if I can find anything about the operation and use of that bus.

I understand your priorities :+1:t2: Just dwelling in the corner of curiosity when I’m looking at your progress. Xiaomi do often keep a copy of the former version after FW upgrade(gateways anyway) as a possible fallback if something fails during update.

Some great work going on here… Thanks.
Looks as if there is a possibility to split the touch control and use it via HA rather than locally, possibly with ControllerX. That would mean that the lamp could be used as a room controller.

Good timing with Easter this weekend to take one of my ‘NoLAN’ lamps apart and investigate options.

It always struck me that given the size of the lamp, it could be used as the host for other functions and hardware extensions/ add-ons.

Yes, that is definitely possible. It is basically a second device in the same enclosure. If we exposes its functionality as a separate ESPHome component, then it’s easy enough to do the routing however you like. Either handle everything locally in the device, or simply expose events to Home Assistant (or a mix, e.g. using short touch for controlling the lamp and using long touch for controlling a room). Not being able to use the front panel that way was a disappointment when I started using the device, so also looking forward to such functionality.

One extra add-on that I would like to attach is a microwave presence module. That would give me an extra motion controller in my bedroom and at my work desk. What I want to try, is insert one or more of these modules in the top lighting part of the device. The only thing I am worried about, is that this nightthrow some unwanted shadows when the light is on. It’s worth the try though.

@rojexx “NoLan lamp”, I quite liked that. Is that Chinese…? :grin:

Microwave sensors penetrate almost anything albeit metal and heavy concrete with reinforcement. Just find a small quality sensor that fits in the bottom. There is room there and will cost you a cop of coffee.

There’s some room in the base of the lamp too yes. The microwave sensors that I have lying around require at least 17mm of vertical space. I didn’t actually try if this would fit, but it looked a bit tight.

I finished up what feels like a million RGB measurements. I translated the results into a table in code.This should be a solid base for an improved RGB color implementation. This is “just” a collection of measurements. The actual logic that uses the new data will be worked on tomorrow.

Hi, thank you for your great work @mmakaay, this is the first time i use a custom component with esphome and homeassistant and i am not sure where to clone the repsoitory. I have a home assistant on a raspberry pi and installed esphome as a addon.

I put the files in:
/config/esphome/custom_components/yeelight_bs2

and in the directory of the component: /config/esphome/schlafzimmerbedlight/custom_components/yeelight_bs2

But I got an error on compile:

Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/lib789/WiFi/WiFi.cpp.o
In file included from src/esphome.h:37:0,
                 from src/main.cpp:3:
src/esphome/components/yeelight_bs2/yeelight_bs2_light_output.h:164:39: error: 'RGBLight' in namespace 'esphome::rgbww::yeelight_bs2' does not name a type
         esphome::rgbww::yeelight_bs2::RGBLight rgb_light_;
                                       ^
In file included from src/esphome.h:37:0,
                 from src/main.cpp:3:
src/esphome/components/yeelight_bs2/yeelight_bs2_light_output.h: In member function 'void esphome::rgbww::YeelightBS2LightOutput::turn_on_in_rgb_mode_(float, float, float, float, float)':
src/esphome/components/yeelight_bs2/yeelight_bs2_light_output.h:202:13: error: 'rgb_light_' was not declared in this scope
             rgb_light_.set_color(red, green, blue, brightness, state);
             ^
*** [/data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/main.cpp.o] Error 1
========================= [FAILED] Took 40.90 seconds =========================

Here is the full logfile:

INFO Reading configuration /config/esphome/SchlafzimmerBedlight.yaml...
INFO Generating C++ source...
INFO Compiling app...
INFO Running:  platformio run -d /config/esphome/schlafzimmerbedlight
Processing schlafzimmerbedlight (board: esp32doit-devkit-v1; framework: arduino; platform: [email protected])
--------------------------------------------------------------------------------
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
PACKAGES: 
 - framework-arduinoespressif32 0.0.0+sha.49b5f52 
 - tool-esptoolpy 1.20600.0 (2.6.0) 
 - toolchain-xtensa32 2.50200.80 (5.2.0)
Library Manager: Installing AsyncTCP-esphome @ 1.1.1
Library Manager: AsyncTCP-esphome @ 1.1.1 has been installed!
Library Manager: Installing ESPAsyncWebServer-esphome @ 1.2.7
Library Manager: ESPAsyncWebServer-esphome @ 1.2.7 has been installed!
Library Manager: Installing dependencies...
Library Manager: Installing ESPAsyncTCP-esphome
Library Manager: ESPAsyncTCP-esphome @ 1.2.3 has been installed!
Library Manager: Installing Hash
Library Manager: Already installed, built-in library
Library Manager: Installing Hash
Library Manager: Already installed, built-in library
Dependency Graph
|-- <AsyncTCP-esphome> 1.1.1
|-- <ESPmDNS> 1.0
|   |-- <WiFi> 1.0
|-- <FS> 1.0
|-- <ESPAsyncWebServer-esphome> 1.2.7
|   |-- <AsyncTCP-esphome> 1.1.1
|   |-- <FS> 1.0
|   |-- <WiFi> 1.0
|-- <Wire> 1.0.1
|-- <DNSServer> 1.1.0
|   |-- <WiFi> 1.0
|-- <Update> 1.0
|-- <WiFi> 1.0
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/api/api_connection.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/api/api_pb2.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/api/api_pb2_service.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/api/api_server.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/api/list_entities.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/api/proto.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/api/subscribe_state.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/api/user_services.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/api/util.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/captive_portal/captive_portal.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/gpio/output/gpio_binary_output.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/i2c/i2c.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/ledc/ledc_output.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/light/addressable_light.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/light/light_state.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/logger/logger.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/ota/ota_component.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/output/automation.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/output/float_output.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/web_server_base/web_server_base.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/wifi/wifi_component.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/wifi/wifi_component_esp32.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/components/wifi/wifi_component_esp8266.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/core/application.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/core/component.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/core/controller.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/core/esphal.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/core/helpers.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/core/log.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/core/preferences.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/core/scheduler.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/esphome/core/util.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/main.cpp.o
Generating partitions /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/partitions.bin
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/libff1/AsyncTCP-esphome/AsyncTCP.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/lib789/WiFi/ETH.cpp.o
Compiling /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/lib789/WiFi/WiFi.cpp.o
In file included from src/esphome.h:37:0,
                 from src/main.cpp:3:
src/esphome/components/yeelight_bs2/yeelight_bs2_light_output.h:164:39: error: 'RGBLight' in namespace 'esphome::rgbww::yeelight_bs2' does not name a type
         esphome::rgbww::yeelight_bs2::RGBLight rgb_light_;
                                       ^
In file included from src/esphome.h:37:0,
                 from src/main.cpp:3:
src/esphome/components/yeelight_bs2/yeelight_bs2_light_output.h: In member function 'void esphome::rgbww::YeelightBS2LightOutput::turn_on_in_rgb_mode_(float, float, float, float, float)':
src/esphome/components/yeelight_bs2/yeelight_bs2_light_output.h:202:13: error: 'rgb_light_' was not declared in this scope
             rgb_light_.set_color(red, green, blue, brightness, state);
             ^
*** [/data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/src/main.cpp.o] Error 1
========================= [FAILED] Took 40.90 seconds =========================

My /config/esphome/schlafzimmerbedlight.yaml looks like this (i changed the passwords):

substitutions:
  name: schlafzimmerbedlight
  friendly_name: Svens Nachtischlampe
  transition_length: 1s


esphome:
  name: $name
  platform: ESP32
  board: esp32doit-devkit-v1
  platformio_options:
    # Special platform + package 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.
    platform: [email protected]
    platform_packages: |-4
          framework-arduinoespressif32 @ https://github.com/pauln/arduino-esp32.git#solo-no-mac-crc/1.0.4

wifi:
  ssid: "Anders"
  password: "i-dont-tell-you"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Schlafzimmerbedlight"
    password: "this-is-wrong"

captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:

light:
  - platform: yeelight_bs2
    name: ${friendly_name} Custom Light
    red: led_red
    green: led_green
    blue: led_blue
    white: led_white
    master1: master1
    master2: master2
    default_transition_length: 1s
    effects:
      - random:
          name: "Slow Random"
          transition_length: 30s
          update_interval: 30s
      - random:
          name: "Fast Random"
          transition_length: 3s
          update_interval: 4s

# The device uses two I2C busses.
i2c:
  - id: eeprom_i2c
    sda: GPIO17
    scl: GPIO18
    scan: True
  - id: front_panel_i2c
    sda: GPIO21
    scl: GPIO19
    scan: True

# The device uses six GPIO pins for driving the LED circuitry.
output:
  - platform: gpio
    id: master1
    pin: GPIO33
  - platform: gpio
    id: master2
    pin: GPIO4
  - platform: ledc
    id: led_red
    pin: GPIO13
  - platform: ledc
    id: led_green
    pin: GPIO14
  - platform: ledc
    id: led_blue
    pin: GPIO5
  - platform: ledc
    id: led_white
    pin: GPIO12


BTW: Is this the right place to ask or should I fill an githib issue for this?

Sven

Hi, I found out, that there is/was a error in the git reo, i checked out the version from yesterday

cd /config/esphome/custom_components/yeelight_bs2/
git checkout 8b12a5900b48c72a1c9d6ea8578c57cc88cc1bb8

and now it compiles.