Add device power usage display page, enable device buttons in HA

This commit is contained in:
2026-08-18 13:12:33 +02:00
parent bb1f514fee
commit d508c3c6f2
+195 -16
View File
@@ -118,6 +118,12 @@ font:
glyphsets: glyphsets:
- GF_Latin_Kernel - GF_Latin_Kernel
glyphs: ["äöüÄÖÜß"] glyphs: ["äöüÄÖÜß"]
- file: "fonts/Roboto-Regular.ttf"
id: font_device
size: 13
glyphsets:
- GF_Latin_Kernel
glyphs: ["äöüÄÖÜß"]
- file: "fonts/materialdesignicons-webfont.ttf" - file: "fonts/materialdesignicons-webfont.ttf"
id: font_icon id: font_icon
size: 24 size: 24
@@ -143,6 +149,10 @@ globals:
type: bool type: bool
restore_value: true restore_value: true
initial_value: 'false' initial_value: 'false'
- id: device_usage_view
type: int
restore_value: true
initial_value: '0'
sensor: sensor:
# WiFi signal strength # WiFi signal strength
@@ -170,10 +180,118 @@ sensor:
id: grid_export_energy_daily id: grid_export_energy_daily
entity_id: sensor.energy_export_daily entity_id: sensor.energy_export_daily
internal: true internal: true
- platform: homeassistant
id: hallway_fragrance_power
entity_id: sensor.flur_raumduft_power
internal: true
- platform: homeassistant
id: cellar_power
entity_id: sensor.keller_power
internal: true
- platform: homeassistant
id: sideboard_power
entity_id: sensor.kuche_anrichte_power
internal: true
- platform: homeassistant
id: kitchen_music_power
entity_id: sensor.kuche_musik_power
internal: true
- platform: homeassistant
id: bedroom_bed_power
entity_id: sensor.schlafzimmer_bett_power
internal: true
- platform: homeassistant
id: bedroom_cinema_power
entity_id: sensor.schlafzimmer_heimkino_power
internal: true
- platform: homeassistant
id: desk_decoration_power
entity_id: sensor.schreibtisch_deko_power
internal: true
- platform: homeassistant
id: desk_power
entity_id: sensor.schreibtisch_power
internal: true
- platform: homeassistant
id: server_room_power
entity_id: sensor.serverraum_power
internal: true
- platform: homeassistant
id: living_room_cinema_power
entity_id: sensor.wohnzimmer_heimkino_power
internal: true
- platform: homeassistant
id: games_cabinet_power
entity_id: sensor.wohnzimmer_spieleschrank_power
internal: true
- platform: homeassistant
id: refrigerator_power
entity_id: sensor.tz3000_ww6drja5_ts011f_leistung
internal: true
- platform: homeassistant
id: coffee_machine_power
entity_id: sensor.kaffeemaschine_leistung_2
internal: true
- platform: homeassistant
id: dryer_power
entity_id: sensor.ikea_of_sweden_inspelning_smart_plug_leistung
internal: true
- platform: homeassistant
id: washing_machine_power
entity_id: sensor.waschmaschine_leistung
internal: true
- platform: homeassistant
id: arcade_power
entity_id: sensor.arcade_automat_leistung
internal: true
- platform: homeassistant
id: dishwasher_power
entity_id: sensor.spulmaschine_leistung
internal: true
- platform: homeassistant
id: microwave_power
entity_id: sensor.waschetrockner_leistung
internal: true
- platform: wireguard - platform: wireguard
latest_handshake: latest_handshake:
name: 'WireGuard Latest Handshake' name: 'WireGuard Latest Handshake'
script:
- id: show_previous_page
then:
- lambda: id(page_index) = (id(page_index) + 2 - 1) % 2;
- component.update: tft
- id: toggle_page_mode
then:
- lambda: |-
if (id(page_index) == 0) {
id(page_one_gauge_view) = !id(page_one_gauge_view);
} else {
id(device_usage_view) = (id(device_usage_view) + 1) % 2;
}
- component.update: tft
- id: show_next_page
then:
- lambda: id(page_index) = (id(page_index) + 1) % 2;
- component.update: tft
button:
- platform: template
name: "Zurück"
icon: mdi:arrow-left
on_press:
- script.execute: show_previous_page
- platform: template
name: "Modus"
icon: mdi:view-dashboard-outline
on_press:
- script.execute: toggle_page_mode
- platform: template
name: "Weiter"
icon: mdi:arrow-right
on_press:
- script.execute: show_next_page
binary_sensor: binary_sensor:
- platform: wireguard - platform: wireguard
status: status:
@@ -189,9 +307,7 @@ binary_sensor:
inverted: true inverted: true
id: button_middle id: button_middle
on_press: on_press:
then: - script.execute: toggle_page_mode
- lambda: id(page_one_gauge_view) = !id(page_one_gauge_view);
- component.update: tft
# M5Stack Core button A (left). GPIO39 is input-only and has an external pull-up. # M5Stack Core button A (left). GPIO39 is input-only and has an external pull-up.
- platform: gpio - platform: gpio
@@ -201,10 +317,7 @@ binary_sensor:
inverted: true inverted: true
id: button_left id: button_left
on_press: on_press:
then: - script.execute: show_previous_page
- lambda: |-
id(page_index) = (id(page_index) + 2 - 1) % 2;
- component.update: tft
# M5Stack Core button C (right). GPIO37 is input-only and has an external pull-up. # M5Stack Core button C (right). GPIO37 is input-only and has an external pull-up.
- platform: gpio - platform: gpio
pin: pin:
@@ -213,10 +326,7 @@ binary_sensor:
inverted: true inverted: true
id: button_right id: button_right
on_press: on_press:
then: - script.execute: show_next_page
- lambda: |-
id(page_index) = (id(page_index) + 1) % 2;
- component.update: tft
text_sensor: text_sensor:
- platform: wireguard - platform: wireguard
@@ -353,10 +463,79 @@ display:
it.printf(gauge_center_x, 169, id(font_title), solar_gauge_color, TextAlign::TOP_CENTER, "-- W"); it.printf(gauge_center_x, 169, id(font_title), solar_gauge_color, TextAlign::TOP_CENTER, "-- W");
} }
} else { } else {
it.printf(160, 45, id(font_title), Color::WHITE, TextAlign::TOP_CENTER, // Page 2 lists nine consumers at once in two columns; button B changes group.
"Weitere Seite"); const int device_count = 18;
it.printf(160, 95, id(font_small), Color::WHITE, TextAlign::TOP_CENTER, const int usage_group = id(device_usage_view);
"Für zusätzliche Werte vorbereitet"); const int page_start = usage_group * 9;
const char *device_names[device_count] = {
"Raumduft", "Keller", "Anrichte", "Musik", "Bett", "HK Schlafzimmer",
"Deko", "Schreibtisch", "Serverraum", "HK Wohnzimmer", "Spieleschrank",
"Kühlschrank", "Kaffeemaschine", "Wäschetrockner", "Waschmaschine", "Arcade",
"Spülmaschine", "Mikrowelle"};
float device_values[device_count] = {
id(hallway_fragrance_power).state, id(cellar_power).state, id(sideboard_power).state,
id(kitchen_music_power).state, id(bedroom_bed_power).state, id(bedroom_cinema_power).state,
id(desk_decoration_power).state, id(desk_power).state, id(server_room_power).state,
id(living_room_cinema_power).state, id(games_cabinet_power).state, id(refrigerator_power).state,
id(coffee_machine_power).state, id(dryer_power).state, id(washing_machine_power).state,
id(arcade_power).state, id(dishwasher_power).state, id(microwave_power).state};
bool device_has_state[device_count] = {
id(hallway_fragrance_power).has_state(), id(cellar_power).has_state(), id(sideboard_power).has_state(),
id(kitchen_music_power).has_state(), id(bedroom_bed_power).has_state(), id(bedroom_cinema_power).has_state(),
id(desk_decoration_power).has_state(), id(desk_power).has_state(), id(server_room_power).has_state(),
id(living_room_cinema_power).has_state(), id(games_cabinet_power).has_state(), id(refrigerator_power).has_state(),
id(coffee_machine_power).has_state(), id(dryer_power).has_state(), id(washing_machine_power).has_state(),
id(arcade_power).has_state(), id(dishwasher_power).has_state(), id(microwave_power).has_state()};
Color device_colors[device_count] = {
Color(255, 170, 40), Color(69, 189, 255), Color(170, 116, 217), Color(93, 207, 140),
Color(238, 112, 112), Color(107, 139, 255), Color(255, 130, 180), Color(122, 204, 174),
Color(240, 195, 90), Color(151, 120, 220), Color(91, 189, 193), Color(212, 132, 82),
Color(143, 190, 223), Color(233, 106, 142), Color(132, 205, 92), Color(255, 181, 80),
Color(111, 167, 229), Color(190, 137, 226)};
// The title uses the free area to the left of the status indicators.
it.printf(12, 10, id(font_device), Color::WHITE, "Geräteverbrauch");
for (int display_index = 0; display_index < 9; display_index++) {
const int index = page_start + display_index;
const int column = display_index % 2;
const int row = display_index / 2;
const int x = column == 0 ? 12 : 166;
const int y = 43 + row * 25;
if (device_has_state[index]) {
it.printf(x, y, id(font_device), device_colors[index], "%s: %.0f W",
device_names[index], device_values[index]);
} else {
it.printf(x, y, id(font_device), device_colors[index], "%s: -- W", device_names[index]);
}
}
// The stacked bar always represents all 18 consumer devices, not only this view's rows.
const int bar_x = 12;
const int bar_y = 180;
const int bar_width = 296;
const int bar_height = 18;
float usage_sum = 0.0f;
int last_active = -1;
for (int index = 0; index < device_count; index++) {
if (device_has_state[index] && device_values[index] > 0.0f) {
usage_sum += device_values[index];
last_active = index;
}
}
it.filled_rectangle(bar_x, bar_y, bar_width, bar_height, Color(42, 42, 42));
if (usage_sum > 0.0f) {
int cursor_x = bar_x;
for (int index = 0; index < device_count; index++) {
if (!device_has_state[index] || device_values[index] <= 0.0f) continue;
const int segment_width = index == last_active
? bar_x + bar_width - cursor_x
: static_cast<int>(device_values[index] * bar_width / usage_sum);
if (segment_width > 0) {
it.filled_rectangle(cursor_x, bar_y, segment_width, bar_height, device_colors[index]);
cursor_x += segment_width;
}
}
}
} }
// Labels correspond to the left (A) and right (C) hardware buttons. // Labels correspond to the left (A) and right (C) hardware buttons.
@@ -369,5 +548,5 @@ display:
"Ansicht · 1 / 2"); "Ansicht · 1 / 2");
} else { } else {
it.printf(160, 239, id(font_small), Color::WHITE, TextAlign::BOTTOM_CENTER, it.printf(160, 239, id(font_small), Color::WHITE, TextAlign::BOTTOM_CENTER,
"2 / 2"); "Geräte %d / 2", id(device_usage_view) + 1);
} }