18static constexpr uint32_t ECHO_TIMEOUT_ID = 0;
27PROGMEM_STRING_TABLE(ColorModeNames,
"onoff",
"brightness",
"white",
"color_temp",
"hs",
"xy",
"rgb",
"rgbw",
"rgbww");
28const uint8_t COLOR_MODES[]
PROGMEM = {
29 static_cast<uint8_t
>(ColorMode::ON_OFF),
30 static_cast<uint8_t
>(ColorMode::BRIGHTNESS),
31 static_cast<uint8_t
>(ColorMode::WHITE),
32 static_cast<uint8_t
>(ColorMode::COLOR_TEMPERATURE),
35optional<ColorMode> parse_color_mode(
StringRef name) {
44bool parse_rgb(
const char *text, std::array<uint8_t, 3> &values) {
45 for (
auto &value : values) {
46 while (*text ==
' ' || *text ==
',' || *text ==
'(') {
49 if (*text <
'0' || *text >
'9') {
53 while (*text >=
'0' && *text <=
'9') {
54 number = number * 10 + (*text++ -
'0');
59 value =
static_cast<uint8_t
>(number);
61 while (*text ==
' ' || *text ==
',' || *text ==
')') {
78 char name[ColorModeNames::MAX_LENGTH + 1];
83 if (
length <
sizeof(name)) {
90 if (
mode.has_value()) {
93 ESP_LOGW(TAG,
"'%s': Unknown color mode in '%s'", this->
entity_id_, value.
c_str());
98 ESP_LOGW(TAG,
"'%s': Can't parse 'supported_color_modes' value '%s'", this->
entity_id_, value.
c_str());
102 ESP_LOGW(TAG,
"'%s': No color mode found in '%s', keeping the current ones", this->
entity_id_, value.
c_str());
105 ESP_LOGD(TAG,
"'%s': Supported color modes retrieved: %s", this->
entity_id_, value.
c_str());
111 server->subscribe_home_assistant_state(this->
entity_id_,
"min_color_temp_kelvin", [
this](
StringRef value) {
112 if (
auto kelvin = this->
parse_integer_(
"min_color_temp_kelvin", value, UINT16_MAX)) {
117 server->subscribe_home_assistant_state(this->
entity_id_,
"max_color_temp_kelvin", [
this](
StringRef value) {
118 if (
auto kelvin = this->
parse_integer_(
"max_color_temp_kelvin", value, UINT16_MAX)) {
125 server->subscribe_home_assistant_state(this->
entity_id_,
nullptr, [
this](
StringRef value) {
131 ESP_LOGW(TAG,
"'%s': Can't parse '%s' as state!", this->
entity_id_, value.
c_str());
136 server->subscribe_home_assistant_state(this->
entity_id_,
"color_mode", [
this](
StringRef value) {
140 auto mode = parse_color_mode(value);
141 if (!
mode.has_value()) {
142 ESP_LOGE(TAG,
"'%s': Can't parse 'color_mode' value '%s' as color mode!", this->
entity_id_, value.
c_str());
147 server->subscribe_home_assistant_state(this->
entity_id_,
"brightness", [
this](
StringRef value) {
148 if (
auto brightness = this->
parse_integer_(
"brightness", value, 255)) {
152 server->subscribe_home_assistant_state(this->
entity_id_,
"color_temp_kelvin", [
this](
StringRef value) {
153 if (
auto kelvin = this->
parse_integer_(
"color_temp_kelvin", value, UINT16_MAX)) {
157 server->subscribe_home_assistant_state(this->
entity_id_,
"rgb_color", [
this](
StringRef value) {
161 std::array<uint8_t, 3> rgb;
162 if (!parse_rgb(value.c_str(), rgb)) {
163 ESP_LOGE(TAG,
"'%s': Can't parse 'rgb_color' value '%s'!", this->
entity_id_, value.
c_str());
174 "Homeassistant Light:\n"
184 if (!number.has_value()) {
185 ESP_LOGE(TAG,
"'%s': Can't convert '%s' value '%s' to number!", this->
entity_id_, name, value.c_str());
189 const bool in_range = *number >= 1.0f && *number <= max;
191 ESP_LOGW(TAG,
"'%s': '%s' value %.0f is out of range!", this->
entity_id_, name, *number);
194 return static_cast<uint16_t
>(*number);
233 if (imported.
color_mode != ColorMode::UNKNOWN) {
242 if (
mode == ColorMode::COLOR_TEMPERATURE) {
244 }
else if (
mode == ColorMode::RGB) {
251 }
else if (
mode == ColorMode::WHITE) {
265 ESP_LOGD(TAG,
"'%s': Report dropped, a local change is on its way", this->
entity_id_);
268 ESP_LOGV(TAG,
"'%s': Took over the state reported by Home Assistant", this->
entity_id_);
292 if (!*outgoing.
state) {
300 case ColorMode::COLOR_TEMPERATURE:
312 ESP_LOGW(TAG,
"'%s': Nothing reported yet to fall back to, the light keeps the unsent change", this->
entity_id_);
337 ESP_LOGD(TAG,
"'%s': Applying the report that arrived during the transition", this->
entity_id_);
346 if (values.
is_on()) {
349 case ColorMode::ON_OFF:
351 case ColorMode::WHITE:
354 case ColorMode::COLOR_TEMPERATURE:
377 ESP_LOGW(TAG,
"'%s': Ended at the state Home Assistant already has, nothing to send (a flash never is)",
380 ESP_LOGD(TAG,
"'%s': Home Assistant already has this state", this->
entity_id_);
385 ESP_LOGE(TAG,
"'%s': No clients connected to API server, change lost", this->
entity_id_);
389#ifdef USE_API_WIZARD_LINKED_INPUTS
391 ESP_LOGW(TAG,
"'%s': No entity ID set yet", LOG_STR_ARG(
state->get_log_name()));
398 static const char SERVICE_TURN_ON[]
PROGMEM =
"light.turn_on";
399 static const char SERVICE_TURN_OFF[]
PROGMEM =
"light.turn_off";
400 static const char ENTITY_ID_KEY[]
PROGMEM =
"entity_id";
401 static const char BRIGHTNESS_KEY[]
PROGMEM =
"brightness";
402 static const char WHITE_KEY[]
PROGMEM =
"white";
403 static const char COLOR_TEMP_KELVIN_KEY[]
PROGMEM =
"color_temp_kelvin";
404 static const char RGB_COLOR_KEY[]
PROGMEM =
"rgb_color";
408 char color_temp_buf[6];
413 auto &entity_id = resp.
data.emplace_back();
418 auto &entry = resp.
data.emplace_back();
422 if (!*outgoing.
state) {
426 if (outgoing.
color_mode != ColorMode::ON_OFF) {
430 level_buf,
sizeof(level_buf), outgoing.
brightness);
448 outgoing.
rgb[0], outgoing.
rgb[1], outgoing.
rgb[2])));
457 ESP_LOGW(TAG,
"'%s': Home Assistant did not report the change back", this->
entity_id_);
BedjetMode mode
BedJet operating mode.
bool cancel_timeout(const char *name)
Cancel a timeout function.
void set_timeout(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a const char* name.
void defer(const char *name, std::function< void()> &&f)
Defer a callback to the next loop() call with a const char* name.
constexpr void insert(ValueType value)
Add a single value to the set (std::set compatibility)
constexpr bool empty() const
Check if the set is empty.
A string that may live in flash (on ESP8266): pointer and length, with no byte-reading operations.
static constexpr ProgmemStringRef from_lit(const char(&s)[N])
A PROGMEM char array, with its length known at compile time.
StringRef is a reference to a string owned by something else.
constexpr const char * c_str() const
constexpr size_type size() const
void send_homeassistant_action(const HomeassistantActionRequest &call)
void subscribe_home_assistant_state(const char *entity_id, const char *attribute, std::function< void(StringRef)> &&f)
FixedVector< HomeassistantServiceMap > data
FixedVector< HomeassistantServiceMap > data_template
void dump_config() override
void fall_back_()
Returns the light to the reported state after a change that did not reach Home Assistant.
optional< uint16_t > parse_integer_(const char *name, StringRef value, uint16_t max)
Parses a Home Assistant attribute as an integer from 1 to max, logging anything else.
void on_report_(bool changed)
A state or attribute report: answers a pending echo when it changed something, and schedules the appl...
void schedule_apply_()
Schedules apply_imported_() once for the attributes of one update.
void write_state(light::LightState *state) override
void update_state(light::LightState *state) override
light::LightState * state_
void import_(T &field, const T &value)
Takes over a reported attribute, reporting whether it changed.
bool is_imported_(const Attributes &outgoing) const
True when Home Assistant reported exactly what a change would make of it.
light::LightTraits traits_
uint8_t report_timeout_s_
This class represents the color state for a light object.
void set_color_mode(ColorMode color_mode)
Set the color mode of these light color values.
float get_brightness() const
Get the brightness property of these light color values. In range 0.0 to 1.0.
float get_blue() const
Get the blue property of these light color values. In range 0.0 to 1.0.
float get_white() const
Get the white property of these light color values. In range 0.0 to 1.0.
float get_color_temperature() const
Get the color temperature property of these light color values in mired.
void set_brightness(float brightness)
Set the brightness property of these light color values. In range 0.0 to 1.0.
void set_blue(float blue)
Set the blue property of these light color values. In range 0.0 to 1.0.
void set_color_brightness(float brightness)
Set the color brightness property of these light color values. In range 0.0 to 1.0.
void set_color_temperature_kelvin(float color_temperature)
Set the color temperature property of these light color values in kelvin.
bool is_on() const
Get the binary true/false state of these light color values.
float get_green() const
Get the green property of these light color values. In range 0.0 to 1.0.
void set_state(float state)
Set the state of these light color values. In range from 0.0 (off) to 1.0 (on)
ColorMode get_color_mode() const
Get the color mode of these light color values.
void set_white(float white)
Set the white property of these light color values. In range 0.0 to 1.0.
float get_red() const
Get the red property of these light color values. In range 0.0 to 1.0.
void set_green(float green)
Set the green property of these light color values. In range 0.0 to 1.0.
void set_red(float red)
Set the red property of these light color values. In range 0.0 to 1.0.
float get_color_brightness() const
Get the color brightness property of these light color values. In range 0.0 to 1.0.
float get_color_temperature_kelvin() const
Get the color temperature property of these light color values in kelvin.
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
LightColorValues remote_values
The remote color values reported to the frontend.
bool is_transitioning() const
True from the call that starts a transition or flash until it reaches its target.
bool set_external_state(const LightColorValues &values)
Take over the state of a light mirrored from elsewhere: current and target values at once,...
bool called_since_clear() const
True once a call is performed after clear_called(), so an output can tell whether a call came after s...
void set_supported_color_modes(ColorModeMask supported_color_modes)
void set_min_mireds(float min_mireds)
void set_max_mireds(float max_mireds)
APIServer * global_api_server
bool parse_python_list(StringRef src, C &&on_char, O &&on_item)
Walk a list attribute as Home Assistant sends it: the Python repr of a list of strings,...
bool is_unset(StringRef value)
True for what Home Assistant reports when there is no value: "None" for an attribute that is not set,...
PROGMEM_STRING_TABLE(UnsetValues, "None", "unavailable", "unknown")
ESPHOME_LOG_TAG(TAG, "homeassistant.binary_sensor")
constexpr ColorMode COLOR_MODE_LOOKUP[] PROGMEM
ColorMode
Color modes are a combination of color capabilities that can be used at the same time.
@ RGB
Color can be controlled using RGB format (includes a brightness control for the color).
value[LAYOUT.day_index()]
ParseOnOffState parse_on_off(const char *str, const char *on, const char *off)
Parse a string that contains either on, off or toggle.
int16_t progmem_string_table_find(const char *value, size_t len)
The index of the string value (len bytes, in RAM) in a PROGMEM_STRING_TABLE, or -1 when it is not one...
optional< T > parse_number(const char *str)
Parse an unsigned decimal number from a null-terminated string.
uint8_t progmem_read_byte(const uint8_t *addr)
What Home Assistant reported last, in its own units.
light::ColorMode color_mode
std::array< uint8_t, 3 > rgb
uint16_t color_temp_kelvin