pipish/render.h

97 lines
3.4 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_baseline(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 baseline;
}
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_baseline("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) >= 2000) {
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
ESPTime now = id(rtc_time).now();
float seconds = now.second + now.minute * 60 + now.hour * 3600;
int rounded_minutes = static_cast<int>(std::roundf(seconds / 60 / 5)) * 5;
it.printf(15, 8, &id(clock_font), TextAlign::TOP_LEFT, "%d:%02d",
rounded_minutes / 60, rounded_minutes % 60);
float outside = (!std::isnan(id(ruuvi_outside_temperature).state)
? id(ruuvi_outside_temperature).state
: id(outside_temperature).state);
int right_width = measure_width("123||", id(normal_font));
render_sensor(it, kWidth - right_width / 2, kHeight * 7 / 100, outside, "°C",
"Outside");
render_sensor(it, kWidth - right_width / 2, kHeight * 58 / 100,
id(scd40_temperature).state, "°C", "Inside");
int bottom_width = measure_width("1999|", id(normal_font));
render_sensor(it, bottom_width / 2 + kWidth * 0 / 100, kHeight * 58 / 100,
id(scd40_co2).state, "", "CO2 ppm");
render_sensor(it, bottom_width / 2 + kWidth * 33 / 100, kHeight * 58 / 100,
id(solar_power).state, "W", "Solar");
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;
}
}
}
}