mirror of
https://github.com/esphome/esphome.git
synced 2024-12-12 08:24:55 +01:00
Add support for TextPanels grabbing their content from Sensors and TextSensors
This commit is contained in:
parent
c018ba2ac3
commit
4e37a09310
3 changed files with 89 additions and 17 deletions
|
@ -3,6 +3,8 @@
|
|||
#include "esphome/components/display/display.h"
|
||||
#include "esphome/components/display/rect.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
namespace esphome {
|
||||
namespace graphical_layout {
|
||||
|
@ -14,10 +16,47 @@ static const int TEXT_ALIGN_Y_MASK =
|
|||
|
||||
void TextPanel::dump_config(int indent_depth, int additional_level_depth) {
|
||||
this->dump_config_base_properties(TAG, indent_depth);
|
||||
std::string text = this->text_.value();
|
||||
std::string text = this->text_input_.value();
|
||||
ESP_LOGCONFIG(TAG, "%*sText Align: %s", indent_depth, "",
|
||||
LOG_STR_ARG(display::text_align_to_string(this->text_align_)));
|
||||
ESP_LOGCONFIG(TAG, "%*sText: %s", indent_depth, "", text.c_str());
|
||||
if (this->sensor_ != nullptr) {
|
||||
ESP_LOGCONFIG(TAG, "%*sSensor: %s", indent_depth, "", this->sensor_->get_name());
|
||||
}
|
||||
if (this->text_sensor_ != nullptr) {
|
||||
ESP_LOGCONFIG(TAG, "%*sText Sensor: %s", indent_depth, "", this->text_sensor_->get_name());
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, "%*sHas Text Formatter: %s", indent_depth, "", YESNO(!this->text_formatter_.has_value()));
|
||||
}
|
||||
|
||||
void TextPanel::setup_complete() {
|
||||
if (!this->text_formatter_.has_value()) {
|
||||
this->text_formatter_ = [this](const std::string string) {
|
||||
return string;
|
||||
};
|
||||
}
|
||||
|
||||
if (this->sensor_ != nullptr) {
|
||||
// Need to setup the text callback for the sensor
|
||||
this->text_ = [this]() {
|
||||
std::stringstream stream;
|
||||
stream << std::fixed << std::setprecision(this->sensor_->get_accuracy_decimals()) << this->sensor_->get_state();
|
||||
return this->text_formatter_.value(stream.str());
|
||||
};
|
||||
}
|
||||
|
||||
if (this->text_sensor_ != nullptr) {
|
||||
// Need to setup the text callback to the TextSensor
|
||||
this->text_ = [this]() {
|
||||
return this->text_formatter_.value(this->text_sensor_->get_state());
|
||||
};
|
||||
}
|
||||
|
||||
if (this->text_input_.has_value()) {
|
||||
this->text_ = [this]() {
|
||||
return this->text_formatter_.value(this->text_input_.value());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
display::Rect TextPanel::measure_item_internal(display::Display *display) {
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "esphome/components/graphical_layout/graphical_layout.h"
|
||||
#include "esphome/components/font/font.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/text_sensor/text_sensor.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace graphical_layout {
|
||||
|
@ -15,8 +17,12 @@ class TextPanel : public LayoutItem {
|
|||
display::Rect measure_item_internal(display::Display *display) override;
|
||||
void render_internal(display::Display *display, display::Rect bounds) override;
|
||||
void dump_config(int indent_depth, int additional_level_depth) override;
|
||||
void setup_complete() override;
|
||||
|
||||
template<typename V> void set_text(V text) { this->text_ = text; };
|
||||
template<typename V> void set_text(V text) { this->text_input_ = text; };
|
||||
void set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; };
|
||||
void set_text_sensor(text_sensor::TextSensor *text_sensor) { this->text_sensor_ = text_sensor; };
|
||||
template<typename V> void set_text_formatter(V text_formatter) { this->text_formatter_ = text_formatter; };
|
||||
void set_font(display::BaseFont *font) { this->font_ = font; };
|
||||
void set_foreground_color(Color foreground_color) { this->foreground_color_ = foreground_color; };
|
||||
void set_background_color(Color background_color) { this->background_color_ = background_color; };
|
||||
|
@ -24,6 +30,10 @@ class TextPanel : public LayoutItem {
|
|||
|
||||
protected:
|
||||
TemplatableValue<std::string> text_{};
|
||||
sensor::Sensor *sensor_{nullptr};
|
||||
text_sensor::TextSensor *text_sensor_{nullptr};
|
||||
TemplatableValue<std::string, const std::string> text_formatter_{};
|
||||
TemplatableValue<std::string> text_input_{};
|
||||
display::BaseFont *font_{nullptr};
|
||||
display::TextAlign text_align_{display::TextAlign::TOP_LEFT};
|
||||
Color foreground_color_{COLOR_ON};
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import font, color
|
||||
from esphome.components import font, color, sensor, text_sensor
|
||||
from esphome.components.display import display_ns
|
||||
from esphome.const import CONF_FOREGROUND_COLOR, CONF_BACKGROUND_COLOR
|
||||
from esphome.const import CONF_FOREGROUND_COLOR, CONF_BACKGROUND_COLOR, CONST_SENSOR
|
||||
|
||||
graphical_layout_ns = cg.esphome_ns.namespace("graphical_layout")
|
||||
TextPanel = graphical_layout_ns.class_("TextPanel")
|
||||
|
@ -12,6 +12,8 @@ CONF_TEXT_PANEL = "text_panel"
|
|||
CONF_FONT = "font"
|
||||
CONF_TEXT = "text"
|
||||
CONF_TEXT_ALIGN = "text_align"
|
||||
CONF_TEXT_SENSOR = "text_sensor"
|
||||
CONF_TEXT_FORMATTER = "text_formatter"
|
||||
|
||||
TEXT_ALIGN = {
|
||||
"TOP_LEFT": TextAlign.TOP_LEFT,
|
||||
|
@ -30,15 +32,21 @@ TEXT_ALIGN = {
|
|||
|
||||
|
||||
def get_config_schema(base_item_schema, item_type_schema):
|
||||
return base_item_schema.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(TextPanel),
|
||||
cv.Required(CONF_FONT): cv.use_id(font.Font),
|
||||
cv.Optional(CONF_FOREGROUND_COLOR): cv.use_id(color.ColorStruct),
|
||||
cv.Optional(CONF_BACKGROUND_COLOR): cv.use_id(color.ColorStruct),
|
||||
cv.Required(CONF_TEXT): cv.templatable(cv.string),
|
||||
cv.Optional(CONF_TEXT_ALIGN): cv.enum(TEXT_ALIGN, upper=True),
|
||||
}
|
||||
return cv.All(
|
||||
base_item_schema.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(TextPanel),
|
||||
cv.Required(CONF_FONT): cv.use_id(font.Font),
|
||||
cv.Optional(CONF_FOREGROUND_COLOR): cv.use_id(color.ColorStruct),
|
||||
cv.Optional(CONF_BACKGROUND_COLOR): cv.use_id(color.ColorStruct),
|
||||
cv.Optional(CONF_TEXT): cv.templatable(cv.string),
|
||||
cv.Optional(CONF_TEXT_ALIGN): cv.enum(TEXT_ALIGN, upper=True),
|
||||
cv.Optional(CONF_SENSOR): cv.use_id(sensor.Sensor),
|
||||
cv.Optional(CONF_TEXT_SENSOR): cv.use_id(text_sensor.TextSensor),
|
||||
cv.Optional(CONF_TEXT_FORMATTER): cv.returning_lambda,
|
||||
}
|
||||
),
|
||||
cv.has_exactly_one_key(CONF_TEXT, CONF_SENSOR, CONF_TEXT_SENSOR),
|
||||
)
|
||||
|
||||
|
||||
|
@ -56,10 +64,25 @@ async def config_to_layout_item(pvariable_builder, item_config, child_item_build
|
|||
background_color = await cg.get_variable(background_color_config)
|
||||
cg.add(var.set_background_color(background_color))
|
||||
|
||||
text = await cg.templatable(
|
||||
item_config[CONF_TEXT], args=[], output_type=cg.std_string
|
||||
)
|
||||
cg.add(var.set_text(text))
|
||||
if sensor_config := item_config.get(CONF_SENSOR):
|
||||
sens = await cg.get_variable(sensor_config)
|
||||
cg.add(var.set_sensor(sens))
|
||||
elif text_sensor_config := item_config.get(CONF_TEXT_SENSOR):
|
||||
text_sens = await cg.get_variable(text_sensor_config)
|
||||
cg.add(var.set_text_sensor(text_sens))
|
||||
else:
|
||||
text = await cg.templatable(
|
||||
item_config[CONF_TEXT], args=[], output_type=cg.std_string
|
||||
)
|
||||
cg.add(var.set_text(text))
|
||||
|
||||
if text_formatter_config := item_config.get(CONF_TEXT_FORMATTER):
|
||||
text_formatter = await cg.process_lambda(
|
||||
text_formatter_config,
|
||||
[(cg.std_string, "it")],
|
||||
return_type=cg.std_string,
|
||||
)
|
||||
cg.add(var.set_text_formatter(text_formatter))
|
||||
|
||||
if text_align := item_config.get(CONF_TEXT_ALIGN):
|
||||
cg.add(var.set_text_align(text_align))
|
||||
|
|
Loading…
Reference in a new issue