esphome / feature-requests

ESPHome Feature Request Tracker
https://esphome.io/
406 stars 26 forks source link

Addressable CWWW support (based on WS2811) #2120

Open steeve opened 1 year ago

steeve commented 1 year ago

Describe the problem you have/What new integration you would like

CWWW light strips now come in addressable fashion, such as https://fr.aliexpress.com/item/1005005069644213.html. The two white channels (2700k and 6500k) are mapped are mapped to RED and GREEN channels.

Please describe your use case for this integration and alternatives you've tried:

Be able to set colour temperature for those addressable light strips.

Additional context

I think it's possible to emulate it via a custom light component, or light template in HA. But I'd wager it would make sense to add it directly in ESPHome, since it already has the cwww component. Perhaps the RED and GREEN channels could be exposed as output components?

steeve commented 1 year ago

I sort of got it to work with the following custom light output, but I don't think it's write to create a LightCall at each write_state, since it seems to do networking back to HA, and causes the transition to be skipped completely, and spams the log.

Nevertheless, it demonstrates the point:

light:
  - id: tmp1
    platform: neopixelbus
    variant: WS2811
    pin: GPIO18
    num_leds: 37
    name: "TMP LEDS"
    power_supply: leds_relay

  - platform: custom
    lambda: |-
        auto light_out = new AddressableCWWW(id(tmp1), 2700, 6500);
        App.register_component(light_out);
        return {light_out};

    lights:
      - name: "My Custom Light"
#include "esphome.h"

class AddressableCWWW : public light::AddressableLight {
private:
    light::AddressableLight *src_;
    LightState *src_state_;
    int32_t cwt_;
    int32_t wwt_;

public:
    AddressableCWWW(light::LightState *src_state, int32_t cwt, int32_t wwt) :
        src_(static_cast<light::AddressableLight *>(src_state->get_output())),
        src_state_(src_state),
        cwt_(cwt),
        wwt_(wwt)
    {
    }

    void setup() override {
        this->src_->setup();
    }

    LightTraits get_traits() override {
        auto traits = LightTraits();
        traits.set_supported_color_modes({
            ColorMode::COLD_WARM_WHITE,
            ColorMode::BRIGHTNESS
        });
        traits.set_min_mireds(1000000 / this->wwt_);
        traits.set_max_mireds(1000000 / this->cwt_);
        return traits;
    }

    int32_t size() const {
        return this->src_->size();
    }

    void clear_effect_data() {
        this->src_->clear_effect_data();
    }

    void write_state(LightState *state) override {
        float cwt = 0.0f;
        float wwt = 0.0f;
        state->current_values_as_cwww(&cwt, &wwt, true);

        bool enabled = false;
        state->current_values_as_binary(&enabled);

        this->src_state_->make_call()
            .set_state(enabled)
            .set_blue(0.0f)
            .set_red(wwt)
            .set_green(cwt)
            .set_transition_length(0)
            .perform();
    }

protected:
    ESPColorView get_view_internal(int32_t index) const override {
        return this->src_->get(index);
    }
};
matthewmax09 commented 7 months ago

Hi there,

I have the same fcob cct strips as you, and tried to adapt your script for esp32_rmt_led_strip.

But ran into some errors and was wondering if you might have some tips on how I may tackle this?

error: expected type-specifier before 'AddressableCWWW'

error: could not convert '{light_out}' from '<brace-enclosed initializer list>' to 'std::vector<esphome::light::LightOutput*>'