mirror of
https://github.com/esphome/esphome.git
synced 2025-03-15 07:08:20 +00:00
Merge remote-tracking branch 'origin/dev' into nrf52_core
This commit is contained in:
commit
cad725b621
4
.github/actions/build-image/action.yaml
vendored
4
.github/actions/build-image/action.yaml
vendored
@ -46,7 +46,7 @@ runs:
|
|||||||
|
|
||||||
- name: Build and push to ghcr by digest
|
- name: Build and push to ghcr by digest
|
||||||
id: build-ghcr
|
id: build-ghcr
|
||||||
uses: docker/build-push-action@v6.6.1
|
uses: docker/build-push-action@v6.7.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./docker/Dockerfile
|
file: ./docker/Dockerfile
|
||||||
@ -69,7 +69,7 @@ runs:
|
|||||||
|
|
||||||
- name: Build and push to dockerhub by digest
|
- name: Build and push to dockerhub by digest
|
||||||
id: build-dockerhub
|
id: build-dockerhub
|
||||||
uses: docker/build-push-action@v6.6.1
|
uses: docker/build-push-action@v6.7.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./docker/Dockerfile
|
file: ./docker/Dockerfile
|
||||||
|
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@ -9,6 +9,7 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- "**"
|
- "**"
|
||||||
- "!.github/workflows/*.yml"
|
- "!.github/workflows/*.yml"
|
||||||
|
- "!.github/actions/build-image/*"
|
||||||
- ".github/workflows/ci.yml"
|
- ".github/workflows/ci.yml"
|
||||||
- "!.yamllint"
|
- "!.yamllint"
|
||||||
- "!.github/dependabot.yml"
|
- "!.github/dependabot.yml"
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace light {
|
namespace light {
|
||||||
|
|
||||||
|
enum class LimitMode { CLAMP, DO_NOTHING };
|
||||||
|
|
||||||
template<typename... Ts> class ToggleAction : public Action<Ts...> {
|
template<typename... Ts> class ToggleAction : public Action<Ts...> {
|
||||||
public:
|
public:
|
||||||
explicit ToggleAction(LightState *state) : state_(state) {}
|
explicit ToggleAction(LightState *state) : state_(state) {}
|
||||||
@ -77,7 +79,10 @@ template<typename... Ts> class DimRelativeAction : public Action<Ts...> {
|
|||||||
float rel = this->relative_brightness_.value(x...);
|
float rel = this->relative_brightness_.value(x...);
|
||||||
float cur;
|
float cur;
|
||||||
this->parent_->remote_values.as_brightness(&cur);
|
this->parent_->remote_values.as_brightness(&cur);
|
||||||
float new_brightness = clamp(cur + rel, 0.0f, 1.0f);
|
if ((limit_mode_ == LimitMode::DO_NOTHING) && ((cur < min_brightness_) || (cur > max_brightness_))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
float new_brightness = clamp(cur + rel, min_brightness_, max_brightness_);
|
||||||
call.set_state(new_brightness != 0.0f);
|
call.set_state(new_brightness != 0.0f);
|
||||||
call.set_brightness(new_brightness);
|
call.set_brightness(new_brightness);
|
||||||
|
|
||||||
@ -85,8 +90,18 @@ template<typename... Ts> class DimRelativeAction : public Action<Ts...> {
|
|||||||
call.perform();
|
call.perform();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_min_max_brightness(float min, float max) {
|
||||||
|
this->min_brightness_ = min;
|
||||||
|
this->max_brightness_ = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_limit_mode(LimitMode limit_mode) { this->limit_mode_ = limit_mode; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
LightState *parent_;
|
LightState *parent_;
|
||||||
|
float min_brightness_{0.0};
|
||||||
|
float max_brightness_{1.0};
|
||||||
|
LimitMode limit_mode_{LimitMode::CLAMP};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Ts> class LightIsOnCondition : public Condition<Ts...> {
|
template<typename... Ts> class LightIsOnCondition : public Condition<Ts...> {
|
||||||
|
@ -19,10 +19,15 @@ from esphome.const import (
|
|||||||
CONF_WARM_WHITE,
|
CONF_WARM_WHITE,
|
||||||
CONF_RANGE_FROM,
|
CONF_RANGE_FROM,
|
||||||
CONF_RANGE_TO,
|
CONF_RANGE_TO,
|
||||||
|
CONF_BRIGHTNESS_LIMITS,
|
||||||
|
CONF_LIMIT_MODE,
|
||||||
|
CONF_MIN_BRIGHTNESS,
|
||||||
|
CONF_MAX_BRIGHTNESS,
|
||||||
)
|
)
|
||||||
from .types import (
|
from .types import (
|
||||||
ColorMode,
|
ColorMode,
|
||||||
COLOR_MODES,
|
COLOR_MODES,
|
||||||
|
LIMIT_MODES,
|
||||||
DimRelativeAction,
|
DimRelativeAction,
|
||||||
ToggleAction,
|
ToggleAction,
|
||||||
LightState,
|
LightState,
|
||||||
@ -167,6 +172,15 @@ LIGHT_DIM_RELATIVE_ACTION_SCHEMA = cv.Schema(
|
|||||||
cv.Optional(CONF_TRANSITION_LENGTH): cv.templatable(
|
cv.Optional(CONF_TRANSITION_LENGTH): cv.templatable(
|
||||||
cv.positive_time_period_milliseconds
|
cv.positive_time_period_milliseconds
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_BRIGHTNESS_LIMITS): cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_MIN_BRIGHTNESS, default="0%"): cv.percentage,
|
||||||
|
cv.Optional(CONF_MAX_BRIGHTNESS, default="100%"): cv.percentage,
|
||||||
|
cv.Optional(CONF_LIMIT_MODE, default="CLAMP"): cv.enum(
|
||||||
|
LIMIT_MODES, upper=True, space="_"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -182,6 +196,13 @@ async def light_dim_relative_to_code(config, action_id, template_arg, args):
|
|||||||
if CONF_TRANSITION_LENGTH in config:
|
if CONF_TRANSITION_LENGTH in config:
|
||||||
templ = await cg.templatable(config[CONF_TRANSITION_LENGTH], args, cg.uint32)
|
templ = await cg.templatable(config[CONF_TRANSITION_LENGTH], args, cg.uint32)
|
||||||
cg.add(var.set_transition_length(templ))
|
cg.add(var.set_transition_length(templ))
|
||||||
|
if conf := config.get(CONF_BRIGHTNESS_LIMITS):
|
||||||
|
cg.add(
|
||||||
|
var.set_min_max_brightness(
|
||||||
|
conf[CONF_MIN_BRIGHTNESS], conf[CONF_MAX_BRIGHTNESS]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
cg.add(var.set_limit_mode(conf[CONF_LIMIT_MODE]))
|
||||||
return var
|
return var
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,6 +26,13 @@ COLOR_MODES = {
|
|||||||
"RGB_COLD_WARM_WHITE": ColorMode.RGB_COLD_WARM_WHITE,
|
"RGB_COLD_WARM_WHITE": ColorMode.RGB_COLD_WARM_WHITE,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Limit modes
|
||||||
|
LimitMode = light_ns.enum("LimitMode", is_class=True)
|
||||||
|
LIMIT_MODES = {
|
||||||
|
"CLAMP": LimitMode.CLAMP,
|
||||||
|
"DO_NOTHING": LimitMode.DO_NOTHING,
|
||||||
|
}
|
||||||
|
|
||||||
# Actions
|
# Actions
|
||||||
ToggleAction = light_ns.class_("ToggleAction", automation.Action)
|
ToggleAction = light_ns.class_("ToggleAction", automation.Action)
|
||||||
LightControlAction = light_ns.class_("LightControlAction", automation.Action)
|
LightControlAction = light_ns.class_("LightControlAction", automation.Action)
|
||||||
|
@ -97,6 +97,7 @@ CONF_BOARD_FLASH_MODE = "board_flash_mode"
|
|||||||
CONF_BORDER = "border"
|
CONF_BORDER = "border"
|
||||||
CONF_BRANCH = "branch"
|
CONF_BRANCH = "branch"
|
||||||
CONF_BRIGHTNESS = "brightness"
|
CONF_BRIGHTNESS = "brightness"
|
||||||
|
CONF_BRIGHTNESS_LIMITS = "brightness_limits"
|
||||||
CONF_BROKER = "broker"
|
CONF_BROKER = "broker"
|
||||||
CONF_BSSID = "bssid"
|
CONF_BSSID = "bssid"
|
||||||
CONF_BUFFER_SIZE = "buffer_size"
|
CONF_BUFFER_SIZE = "buffer_size"
|
||||||
@ -431,6 +432,7 @@ CONF_LIGHT = "light"
|
|||||||
CONF_LIGHT_ID = "light_id"
|
CONF_LIGHT_ID = "light_id"
|
||||||
CONF_LIGHTNING_ENERGY = "lightning_energy"
|
CONF_LIGHTNING_ENERGY = "lightning_energy"
|
||||||
CONF_LIGHTNING_THRESHOLD = "lightning_threshold"
|
CONF_LIGHTNING_THRESHOLD = "lightning_threshold"
|
||||||
|
CONF_LIMIT_MODE = "limit_mode"
|
||||||
CONF_LINE_THICKNESS = "line_thickness"
|
CONF_LINE_THICKNESS = "line_thickness"
|
||||||
CONF_LINE_TYPE = "line_type"
|
CONF_LINE_TYPE = "line_type"
|
||||||
CONF_LOADED_INTEGRATIONS = "loaded_integrations"
|
CONF_LOADED_INTEGRATIONS = "loaded_integrations"
|
||||||
|
134
esphome/core/bytebuffer.cpp
Normal file
134
esphome/core/bytebuffer.cpp
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#include "bytebuffer.h"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
|
||||||
|
ByteBuffer ByteBuffer::create(size_t capacity) {
|
||||||
|
std::vector<uint8_t> data(capacity);
|
||||||
|
return {data};
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer ByteBuffer::wrap(uint8_t *ptr, size_t len) {
|
||||||
|
std::vector<uint8_t> data(ptr, ptr + len);
|
||||||
|
return {data};
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer ByteBuffer::wrap(std::vector<uint8_t> data) { return {std::move(data)}; }
|
||||||
|
|
||||||
|
void ByteBuffer::set_limit(size_t limit) {
|
||||||
|
assert(limit <= this->get_capacity());
|
||||||
|
this->limit_ = limit;
|
||||||
|
}
|
||||||
|
void ByteBuffer::set_position(size_t position) {
|
||||||
|
assert(position <= this->get_limit());
|
||||||
|
this->position_ = position;
|
||||||
|
}
|
||||||
|
void ByteBuffer::clear() {
|
||||||
|
this->limit_ = this->get_capacity();
|
||||||
|
this->position_ = 0;
|
||||||
|
}
|
||||||
|
uint16_t ByteBuffer::get_uint16() {
|
||||||
|
assert(this->get_remaining() >= 2);
|
||||||
|
uint16_t value;
|
||||||
|
if (endianness_ == LITTLE) {
|
||||||
|
value = this->data_[this->position_++];
|
||||||
|
value |= this->data_[this->position_++] << 8;
|
||||||
|
} else {
|
||||||
|
value = this->data_[this->position_++] << 8;
|
||||||
|
value |= this->data_[this->position_++];
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ByteBuffer::get_uint32() {
|
||||||
|
assert(this->get_remaining() >= 4);
|
||||||
|
uint32_t value;
|
||||||
|
if (endianness_ == LITTLE) {
|
||||||
|
value = this->data_[this->position_++];
|
||||||
|
value |= this->data_[this->position_++] << 8;
|
||||||
|
value |= this->data_[this->position_++] << 16;
|
||||||
|
value |= this->data_[this->position_++] << 24;
|
||||||
|
} else {
|
||||||
|
value = this->data_[this->position_++] << 24;
|
||||||
|
value |= this->data_[this->position_++] << 16;
|
||||||
|
value |= this->data_[this->position_++] << 8;
|
||||||
|
value |= this->data_[this->position_++];
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
uint32_t ByteBuffer::get_uint24() {
|
||||||
|
assert(this->get_remaining() >= 3);
|
||||||
|
uint32_t value;
|
||||||
|
if (endianness_ == LITTLE) {
|
||||||
|
value = this->data_[this->position_++];
|
||||||
|
value |= this->data_[this->position_++] << 8;
|
||||||
|
value |= this->data_[this->position_++] << 16;
|
||||||
|
} else {
|
||||||
|
value = this->data_[this->position_++] << 16;
|
||||||
|
value |= this->data_[this->position_++] << 8;
|
||||||
|
value |= this->data_[this->position_++];
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
uint32_t ByteBuffer::get_int24() {
|
||||||
|
auto value = this->get_uint24();
|
||||||
|
uint32_t mask = (~(uint32_t) 0) << 23;
|
||||||
|
if ((value & mask) != 0)
|
||||||
|
value |= mask;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
uint8_t ByteBuffer::get_uint8() {
|
||||||
|
assert(this->get_remaining() >= 1);
|
||||||
|
return this->data_[this->position_++];
|
||||||
|
}
|
||||||
|
float ByteBuffer::get_float() {
|
||||||
|
auto value = this->get_uint32();
|
||||||
|
return *(float *) &value;
|
||||||
|
}
|
||||||
|
void ByteBuffer::put_uint8(uint8_t value) {
|
||||||
|
assert(this->get_remaining() >= 1);
|
||||||
|
this->data_[this->position_++] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ByteBuffer::put_uint16(uint16_t value) {
|
||||||
|
assert(this->get_remaining() >= 2);
|
||||||
|
if (this->endianness_ == LITTLE) {
|
||||||
|
this->data_[this->position_++] = (uint8_t) value;
|
||||||
|
this->data_[this->position_++] = (uint8_t) (value >> 8);
|
||||||
|
} else {
|
||||||
|
this->data_[this->position_++] = (uint8_t) (value >> 8);
|
||||||
|
this->data_[this->position_++] = (uint8_t) value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void ByteBuffer::put_uint24(uint32_t value) {
|
||||||
|
assert(this->get_remaining() >= 3);
|
||||||
|
if (this->endianness_ == LITTLE) {
|
||||||
|
this->data_[this->position_++] = (uint8_t) value;
|
||||||
|
this->data_[this->position_++] = (uint8_t) (value >> 8);
|
||||||
|
this->data_[this->position_++] = (uint8_t) (value >> 16);
|
||||||
|
} else {
|
||||||
|
this->data_[this->position_++] = (uint8_t) (value >> 16);
|
||||||
|
this->data_[this->position_++] = (uint8_t) (value >> 8);
|
||||||
|
this->data_[this->position_++] = (uint8_t) value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void ByteBuffer::put_uint32(uint32_t value) {
|
||||||
|
assert(this->get_remaining() >= 4);
|
||||||
|
if (this->endianness_ == LITTLE) {
|
||||||
|
this->data_[this->position_++] = (uint8_t) value;
|
||||||
|
this->data_[this->position_++] = (uint8_t) (value >> 8);
|
||||||
|
this->data_[this->position_++] = (uint8_t) (value >> 16);
|
||||||
|
this->data_[this->position_++] = (uint8_t) (value >> 24);
|
||||||
|
} else {
|
||||||
|
this->data_[this->position_++] = (uint8_t) (value >> 24);
|
||||||
|
this->data_[this->position_++] = (uint8_t) (value >> 16);
|
||||||
|
this->data_[this->position_++] = (uint8_t) (value >> 8);
|
||||||
|
this->data_[this->position_++] = (uint8_t) value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void ByteBuffer::put_float(float value) { this->put_uint32(*(uint32_t *) &value); }
|
||||||
|
void ByteBuffer::flip() {
|
||||||
|
this->limit_ = this->position_;
|
||||||
|
this->position_ = 0;
|
||||||
|
}
|
||||||
|
} // namespace esphome
|
96
esphome/core/bytebuffer.h
Normal file
96
esphome/core/bytebuffer.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
#include <cinttypes>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
|
||||||
|
enum Endian { LITTLE, BIG };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class modelled on the Java ByteBuffer class. It wraps a vector of bytes and permits putting and getting
|
||||||
|
* items of various sizes, with an automatically incremented position.
|
||||||
|
*
|
||||||
|
* There are three variables maintained pointing into the buffer:
|
||||||
|
*
|
||||||
|
* 0 <= position <= limit <= capacity
|
||||||
|
*
|
||||||
|
* capacity: the maximum amount of data that can be stored
|
||||||
|
* limit: the limit of the data currently available to get or put
|
||||||
|
* position: the current insert or extract position
|
||||||
|
*
|
||||||
|
* In addition a mark can be set to the current position with mark(). A subsequent call to reset() will restore
|
||||||
|
* the position to the mark.
|
||||||
|
*
|
||||||
|
* The buffer can be marked to be little-endian (default) or big-endian. All subsequent operations will use that order.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class ByteBuffer {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Create a new Bytebuffer with the given capacity
|
||||||
|
*/
|
||||||
|
static ByteBuffer create(size_t capacity);
|
||||||
|
/**
|
||||||
|
* Wrap an existing vector in a Bytebufffer
|
||||||
|
*/
|
||||||
|
static ByteBuffer wrap(std::vector<uint8_t> data);
|
||||||
|
/**
|
||||||
|
* Wrap an existing array in a Bytebufffer
|
||||||
|
*/
|
||||||
|
static ByteBuffer wrap(uint8_t *ptr, size_t len);
|
||||||
|
|
||||||
|
// Get one byte from the buffer, increment position by 1
|
||||||
|
uint8_t get_uint8();
|
||||||
|
// Get a 16 bit unsigned value, increment by 2
|
||||||
|
uint16_t get_uint16();
|
||||||
|
// Get a 24 bit unsigned value, increment by 3
|
||||||
|
uint32_t get_uint24();
|
||||||
|
// Get a 32 bit unsigned value, increment by 4
|
||||||
|
uint32_t get_uint32();
|
||||||
|
// signed versions of the get functions
|
||||||
|
uint8_t get_int8() { return (int8_t) this->get_uint8(); };
|
||||||
|
int16_t get_int16() { return (int16_t) this->get_uint16(); }
|
||||||
|
uint32_t get_int24();
|
||||||
|
int32_t get_int32() { return (int32_t) this->get_uint32(); }
|
||||||
|
// Get a float value, increment by 4
|
||||||
|
float get_float();
|
||||||
|
|
||||||
|
// put values into the buffer, increment the position accordingly
|
||||||
|
void put_uint8(uint8_t value);
|
||||||
|
void put_uint16(uint16_t value);
|
||||||
|
void put_uint24(uint32_t value);
|
||||||
|
void put_uint32(uint32_t value);
|
||||||
|
void put_float(float value);
|
||||||
|
|
||||||
|
inline size_t get_capacity() const { return this->data_.size(); }
|
||||||
|
inline size_t get_position() const { return this->position_; }
|
||||||
|
inline size_t get_limit() const { return this->limit_; }
|
||||||
|
inline size_t get_remaining() const { return this->get_limit() - this->get_position(); }
|
||||||
|
inline Endian get_endianness() const { return this->endianness_; }
|
||||||
|
inline void mark() { this->mark_ = this->position_; }
|
||||||
|
inline void big_endian() { this->endianness_ = BIG; }
|
||||||
|
inline void little_endian() { this->endianness_ = LITTLE; }
|
||||||
|
void set_limit(size_t limit);
|
||||||
|
void set_position(size_t position);
|
||||||
|
// set position to 0, limit to capacity.
|
||||||
|
void clear();
|
||||||
|
// set limit to current position, postition to zero. Used when swapping from write to read operations.
|
||||||
|
void flip();
|
||||||
|
// retrieve a pointer to the underlying data.
|
||||||
|
uint8_t *array() { return this->data_.data(); };
|
||||||
|
void rewind() { this->position_ = 0; }
|
||||||
|
void reset() { this->position_ = this->mark_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ByteBuffer(std::vector<uint8_t> data) : data_(std::move(data)) { this->limit_ = this->get_capacity(); }
|
||||||
|
std::vector<uint8_t> data_;
|
||||||
|
Endian endianness_{LITTLE};
|
||||||
|
size_t position_{0};
|
||||||
|
size_t mark_{0};
|
||||||
|
size_t limit_{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace esphome
|
@ -15,6 +15,8 @@ esphome:
|
|||||||
- light.dim_relative:
|
- light.dim_relative:
|
||||||
id: test_monochromatic_light
|
id: test_monochromatic_light
|
||||||
relative_brightness: 5%
|
relative_brightness: 5%
|
||||||
|
brightness_limits:
|
||||||
|
max_brightness: 90%
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
|
@ -15,6 +15,8 @@ esphome:
|
|||||||
- light.dim_relative:
|
- light.dim_relative:
|
||||||
id: test_monochromatic_light
|
id: test_monochromatic_light
|
||||||
relative_brightness: 5%
|
relative_brightness: 5%
|
||||||
|
brightness_limits:
|
||||||
|
max_brightness: 90%
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
|
@ -15,6 +15,8 @@ esphome:
|
|||||||
- light.dim_relative:
|
- light.dim_relative:
|
||||||
id: test_monochromatic_light
|
id: test_monochromatic_light
|
||||||
relative_brightness: 5%
|
relative_brightness: 5%
|
||||||
|
brightness_limits:
|
||||||
|
max_brightness: 90%
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
|
@ -15,6 +15,8 @@ esphome:
|
|||||||
- light.dim_relative:
|
- light.dim_relative:
|
||||||
id: test_monochromatic_light
|
id: test_monochromatic_light
|
||||||
relative_brightness: 5%
|
relative_brightness: 5%
|
||||||
|
brightness_limits:
|
||||||
|
max_brightness: 90%
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
|
@ -15,6 +15,8 @@ esphome:
|
|||||||
- light.dim_relative:
|
- light.dim_relative:
|
||||||
id: test_monochromatic_light
|
id: test_monochromatic_light
|
||||||
relative_brightness: 5%
|
relative_brightness: 5%
|
||||||
|
brightness_limits:
|
||||||
|
max_brightness: 90%
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
|
@ -15,6 +15,8 @@ esphome:
|
|||||||
- light.dim_relative:
|
- light.dim_relative:
|
||||||
id: test_monochromatic_light
|
id: test_monochromatic_light
|
||||||
relative_brightness: 5%
|
relative_brightness: 5%
|
||||||
|
brightness_limits:
|
||||||
|
max_brightness: 90%
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
|
Loading…
x
Reference in New Issue
Block a user