mmakaay / esphome-xiaomi_bslamp2

ESPHome integration for the Xiaomi Mijia Bedside Lamp v2.
Other
219 stars 51 forks source link

[FEATURE] leave power button always on #38

Closed Stewie3112 closed 3 years ago

Stewie3112 commented 3 years ago

First thanks a lot for this firmware, it gave new life to a garbage object after Xiaomi decided to remove lan functionality!

The firmware is working great, but I'd like to edit it to have just the power button illumination always on. I struggled a bit in the configuration, but I guess I'm missing something isolating the sole power button.

Can you please give a hint to accomplish this functionality?

mmakaay commented 3 years ago

What do you mean exactly with the sole power button? Only the power button, not the slider, not the color button?

If that is the requirement, then I have to disappoint you. The hardware simply does not expose that option. Closest thing possible would be power and color button active, slider off.

Stewie3112 commented 3 years ago

Yeah, that is my intention, but I saw later that it's exposed as a single entity. Your suggestion substantially is leaving the slider at zero, as if switched off... better than nothing, any hint how to accomplish this?

mmakaay commented 3 years ago

I will take a look at it tomorrow. First some sleep.

Stewie3112 commented 3 years ago

great!

mmakaay commented 3 years ago

A quick update: I wasn't able to come up with a solution based on the current firmware, which uses I2C codes as seen on the original firmware. There, the closest thing is having the power button, color button and level 1 brightness level active. That looks ugly, so that is not a good option.

I went back to doing some more reverse engineering, and I think I found a way to handle things in such way that you could have only power + color active. As a side effect I seem to have found a way to steer the front panel lighting in a more fine-grained manner. Take a look at this beauty 😄

afbeelding

I'll process these new findings in the firmware code, after which we can get your requirement going.

Stewie3112 commented 3 years ago

then we can control the leds individually? this fw is getting better and better.

I know it's not related to this post, but I noticed a strange behaviour in my two lamps during night mode (both flashed with same settings).

take a look:

lamp number one:

IMG_3630

lamp number two:

IMG_3631

whatever color mode I choose (between the whites) the second one always keep reverting to that orribile green, any idea on the cause? I'm starting to think about a defective unit

mmakaay commented 3 years ago

I'm close to also understanding how to steer the power and color button individually. Check this out:

afbeelding

Mainly did some exploring here. I don't have the code ready yet. But the future of the power button is looking bright.

For the horrible green:

you might want to experiment a bit with the RGB settings for the night light. I have three devices, two in production and one for development, and I see slight differences in the night light range of colors too. One quick check to find a possibly less disturbing color would be to enable the random color effect and then holding the power button to enable the night light mode. The lamp will then change to a different random color every few seconds (no transitions, because they were not feasible at those LED levels). Keep an eye on home assistant or the device logs to see what RGB values work for you. Then you could use those RGB values + brightness 1% to set the lamp to a more pleasant color.

Stewie3112 commented 3 years ago

great, I found a more pleasant color and binded it to night light! also added auto night mode during night and some other custom mods (like disabling the slider and color button functionality when the light is off, or getting out of night mode always in white warm preset). I just miss that illuminated power button to find the lamp in the darkness 😆

mmakaay commented 3 years ago

Things are not yet fully ready, but I got a PoC working on my device. If you already want to play with this, then try out the branch: https://github.com/mmakaay/esphome-xiaomi_bslamp2/tree/better-front-panel-hal

Note that the interface will likely change, so only use this if you're in a real hurry to get it working :-)

light:
  - platform: xiaomi_bslamp2
    on_brightness:
      - if:
          condition:
            text_sensor.state:
                id: ${id_light_mode}
                state: night
          then:
            - output.set_level:
                id: ${id_front_panel_illumination}
                level: 0
          else:
            - if:
                condition:
                    lambda: return x > 0;
                then:
                  - output.set_level:
                      id: ${id_front_panel_illumination}
                      level: !lambda return x;
                else:
                  - output.set_leds:
                      leds: !lambda return xiaomi::bslamp2::LED_POWER;
Stewie3112 commented 3 years ago

thanks, i'll wait to avoid merging my own mods into different codes 👍

mmakaay commented 3 years ago

Do you have changes in the C++ code, or did you implement all your behaviors in the yaml? If something requires a c++ code change, then I want to update my code base to support it out of the box.

Stewie3112 commented 3 years ago

no, just in the yaml

mmakaay commented 3 years ago

Okay, I got some new toys for you. Check out release v1.1.0-RC2 You can either use the main branch for this, or use this version specifically by using this in the YAML config:

external_components:
  - source:
      type: git
      url: https://github.com/mmakaay/esphome-xiaomi_bslamp2
      ref: v1.1.0-RC2

Here's a video showing some things that I implemented using the new features:

https://www.youtube.com/watch?v=nKwnJPETUdw

The relevant parts of code that I wrote for getting this working:

globals:
  - id: current_brightness
    type: float

script:
  - id: on_brightness_script
    mode: restart
    then:
      - if:
          condition:
            text_sensor.state:
                id: ${id_light_mode}
                state: night
          then:
            - front_panel.turn_off_leds: ALL
          else:
            - if:
                condition:
                    lambda: return id(current_brightness) > 0;
                then:
                  - front_panel.set_leds: [ COLOR, POWER ]
                  - if:
                      condition:
                        lambda: return id(current_brightness) < 0.15;
                      then:
                        front_panel.turn_on_leds: 1
                  - if:
                      condition:
                        and:
                          - lambda: return id(current_brightness) >= 0.15;
                          - lambda: return id(current_brightness) < 0.25;
                      then:
                        front_panel.turn_on_leds: 2
                  - if:
                      condition:
                        and:
                          - lambda: return id(current_brightness) >= 0.25;
                          - lambda: return id(current_brightness) < 0.35;
                      then:
                        front_panel.turn_on_leds: 3
                  - if:
                      condition:
                        and:
                          - lambda: return id(current_brightness) >= 0.35;
                          - lambda: return id(current_brightness) < 0.45;
                      then:
                        front_panel.turn_on_leds: 4
                  - if:
                      condition:
                        and:
                          - lambda: return id(current_brightness) >= 0.45;
                          - lambda: return id(current_brightness) < 0.55;
                      then:
                        front_panel.turn_on_leds: 5
                  - if:
                      condition:
                        and:
                          - lambda: return id(current_brightness) >= 0.55;
                          - lambda: return id(current_brightness) < 0.65;
                      then:
                        front_panel.turn_on_leds: 6
                  - if:
                      condition:
                        and:
                          - lambda: return id(current_brightness) >= 0.65;
                          - lambda: return id(current_brightness) < 0.75;
                      then:
                        front_panel.turn_on_leds: 7
                  - if:
                      condition:
                        and:
                          - lambda: return id(current_brightness) >= 0.75;
                          - lambda: return id(current_brightness) < 0.85;
                      then:
                        front_panel.turn_on_leds: 8
                  - if:
                      condition:
                        and:
                          - lambda: return id(current_brightness) >= 0.85;
                          - lambda: return id(current_brightness) < 0.95;
                      then:
                        front_panel.turn_on_leds: 9
                  - if:
                      condition:
                        - lambda: return id(current_brightness) >= 0.95;
                      then:
                        front_panel.turn_on_leds: 10
                else:
                  # A little animation when the brightness is 0 (i.e. "turn off light").
                  - front_panel.set_leds: [ POWER, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, COLOR ]
                  - delay: 70ms
                  - front_panel.set_leds: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
                  - delay: 70ms
                  - front_panel.set_leds: [ 2, 3, 4, 5, 6, 7, 8, 9 ]
                  - delay: 70ms
                  - front_panel.set_leds: [ 3, 4, 5, 6, 7, 8 ]
                  - delay: 70ms
                  - front_panel.set_leds: [ 4, 5, 6, 7 ]
                  - delay: 80ms
                  - front_panel.set_leds: [ 5, 6 ]
                  - delay: 80ms
                  - front_panel.set_leds: 5
                  - delay: 90ms
                  - front_panel.turn_off_leds: ALL
                  - delay: 90ms
                  - front_panel.turn_on_leds: 5
                  - delay: 100ms
                  - front_panel.turn_off_leds: ALL
                  - delay: 100ms
                  - front_panel.turn_on_leds: 5
                  - delay: 100ms
                  - front_panel.turn_off_leds: ALL

light:
  - platform: xiaomi_bslamp2
    id: ...
    name: ...
    on_brightness:
      then:
        - globals.set:
            id: current_brightness
            value: !lambda return x;
        - script.execute: on_brightness_script
Stewie3112 commented 3 years ago

You're the best! Sorry for the late reply, but the last few days have been really busy.

I can confirm that I can finally have the power button always on via:

 on_turn_off:
      then:
        - front_panel.set_leds: POWER

there's a slight delay where the button goes off and then back on, but it's fine anyway!

mmakaay commented 3 years ago

The delay might be because the light is transitioning to off and only then triggering on_turn_off. I would handle all front panel illumination within the on_brightness code. If brightness == 0, then front_panel.set_leds: POWER, otherwise use the default logic. That might just fix the delay.

Thanks for the feedback. I saw that one of my pull requests for ESPHome has been accepted recently, so along with the next ESPHome, I will release the final stable v1.1.0, which will include the code for the individual LED control as well.

mmakaay commented 3 years ago

I just released v1.1.0. Since this includes the code changes for implementing the requested feature, I now close this issue. Thanks for the idea, @Stewie3112 !

Stewie3112 commented 3 years ago

Thanks to you for the amazingly fast support!