89 lines
2.9 KiB
C++
89 lines
2.9 KiB
C++
inline int measure_width(const char* text, esphome::display::BaseFont& font) {
|
|
int width;
|
|
int x_offset;
|
|
int baseline;
|
|
int height;
|
|
font.measure(text, &width, &x_offset, &baseline, &height);
|
|
return width;
|
|
}
|
|
|
|
inline int measure_height(const char* text, esphome::display::BaseFont& font) {
|
|
int width;
|
|
int x_offset;
|
|
int baseline;
|
|
int height;
|
|
font.measure(text, &width, &x_offset, &baseline, &height);
|
|
return height;
|
|
}
|
|
|
|
inline void render_sensor(esphome::display::Display& it, int x, int y,
|
|
float value, std::string unit,
|
|
const std::string& label) {
|
|
int normal_height = measure_height("X", id(normal_font));
|
|
char formatted[20];
|
|
if (std::isnan(value)) {
|
|
it.print(x, y, &id(normal_font), TextAlign::TOP_CENTER, "--");
|
|
} else {
|
|
char value_text[20];
|
|
if (std::abs(value) >= 1000) {
|
|
unit = "k" + unit;
|
|
value /= 1000;
|
|
}
|
|
if (std::abs(value) < 10) {
|
|
sprintf(value_text, "%.1f", value);
|
|
} else {
|
|
sprintf(value_text, "%.0f", value);
|
|
}
|
|
int value_width = measure_width(value_text, id(normal_font));
|
|
int unit_width = measure_width(unit.c_str(), id(small_font));
|
|
int width = value_width + unit_width + 3;
|
|
it.print(x - width / 2, y + normal_height, &id(normal_font),
|
|
TextAlign::BASELINE_LEFT, value_text);
|
|
it.print(x + width / 2 - unit_width, y + normal_height, &id(small_font),
|
|
TextAlign::BASELINE_LEFT, unit.c_str());
|
|
}
|
|
it.print(x, y + normal_height + 3, &id(small_font), TextAlign::TOP_CENTER,
|
|
label.c_str());
|
|
}
|
|
|
|
inline void render(esphome::display::Display& it) {
|
|
constexpr int kHeight = 540;
|
|
constexpr int kWidth = 960;
|
|
|
|
// Clock
|
|
it.strftime(25, 25, &id(clock_font), TextAlign::TOP_LEFT, "%H:%M",
|
|
id(rtc_time).now());
|
|
|
|
int right_width = measure_width("123||", id(normal_font));
|
|
render_sensor(it, kWidth - right_width / 2, kHeight * 0 / 10,
|
|
id(outside_temperature).state, "°C", "Outside");
|
|
render_sensor(it, kWidth - right_width / 2, kHeight * 3 / 10,
|
|
id(lounge_temperature).state, "°C", "Lounge");
|
|
render_sensor(it, kWidth - right_width / 2, kHeight * 6 / 10,
|
|
id(solar_power).state, "W", "Solar");
|
|
render_sensor(it, right_width / 2, kHeight * 6 / 10, id(uptime_sensor).state,
|
|
"s", "Uptime");
|
|
|
|
static const struct {
|
|
float level;
|
|
std::string icon;
|
|
} battery_levels[] = {
|
|
{10, "mdi-battery-alert-variant-outline"},
|
|
{40, "mdi-battery-low"},
|
|
{70, "mdi-battery-medium"},
|
|
{std::numeric_limits<float>::max(), "mdi-battery-high"},
|
|
};
|
|
|
|
// Battery
|
|
float battery_level = id(m5paper_battery_level).state;
|
|
if (!std::isnan(battery_level)) {
|
|
for (const auto& level : battery_levels) {
|
|
if (battery_level <= level.level) {
|
|
it.print(910, 10, &id(battery_font),
|
|
id(material_icons_map)[level.icon].c_str());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|