diff --git a/docs/api.md b/docs/api.md index c6d88c4..72c1d48 100644 --- a/docs/api.md +++ b/docs/api.md @@ -8,7 +8,7 @@ This document provides details on custom services designed for integration with - [Component Color Service (`component_color`)](#component-color-service-component_color): Changes the foreground color of a specified component on the display. - [Component Text Service (`component_text`)](#component-text-service-component_text): Updates the text of a specified component on the display. - [Component Value Service (`component_val`)](#component-value-service-component_val): Updates the value of a specified component on the display. - - [Component Visibility Service (`component_visibility`)](#component-visibility-service-component_visibility): Hides or shows a specified component on the display. + - [Components Visibility Service (`components_visibility`)](#component-visibility-service-components_visibility): Hides or shows a specified component on the display. - [Entity Details Show Service (`entity_details_show`)](#entity-details-show-service-entity_details_show): Displays detailed information for a specific entity. - [Hardware Button State Indication Service (`hw_button_state`)](#hardware-button-state-indication-service-hw_button_state): Updates the visual state (on/off) of the left and right hardware button indicators on the panel. @@ -54,7 +54,7 @@ If you send anything different, the conversion to the RGB565 used by Nextion wil | [`component_color`](#component-color-service-component_color) | [Component Color Service](#component-color-service-component_color) | Changes the foreground color of a specified component on the display. | | [`component_text`](#component-text-service-component_text) | [Component Text Service](#component-text-service-component_text) | Updates the text of a specified component on the display. | | [`component_val`](#component-value-service-component_val) | [Component Value Service](#component-value-service-component_val) | Updates the value of a specified component on the display. | -| [`component_visibility`](#component-visibility-service-component_visibility) | [Component Visibility Service](#component-visibility-service-component_visibility) | Hides or shows a specified component on the display. | +| [`components_visibility`](#component-visibility-service-components_visibility) | [Components Visibility Service](#component-visibility-service-components_visibility) | Hides or shows a specified component on the display. | | [`entity_details_show`](#entity-details-show-service-entity_details_show) | [Entity Details Show Service](#entity-details-show-service-entity_details_show) | Displays detailed information for a specific entity. | | [`hw_button_state`](#hardware-button-state-indication-service-hw_button_state) | [Hardware Button State Indication Service](#hardware-button-state-indication-service-hw_button_state) | Updates the visual state (on/off) of the left and right hardware button indicators on the panel. | | [`icon`](#icon-service-icon) | [Icon Service](#icon-service-icon) | Updates a chip or custom button's icon, color, and visibility. | @@ -197,33 +197,33 @@ data: > > Ensure the `id` accurately matches the component on your display to successfully update its value. -### Component Visibility Service: `component_visibility` -Hides or shows a specified component on the display, allowing for dynamic interface changes. +### Components Visibility Service: `components_visibility` +Hides or shows a list of component on the display, allowing for dynamic interface changes. **Usage:** This service is ideal for creating interactive user interfaces that adapt by hiding or showing certain elements based on user actions, conditions, or events. **Parameters:** -- `id` (string): Identifier of the component to be hidden/shown. It is crucial that this matches the component's ID in your display layout to ensure the correct element is hidden/shown. +- `ids` (string[]): Array of identifiers of the components to be hidden/shown. It is crucial that this matches the component's ID in your display layout to ensure the correct element is hidden/shown. - `visible` (bool): Set to true to show the component, or false to hide it. **Home Assistant Example:** ```yaml service: esphome._component_hide data: - id: "date" # Hides the date display on Home page + ids: [ "date", "time" ] # Hides the date and time display on Home page visible: false ``` > [!NOTE] > Replace with your specific panel name as configured in Home Assistant to ensure correct service execution. > -> Ensure the id matches the component on your display you wish to hide or show. +> Ensure the ids matches the component on your display you wish to hide or show. > [!IMPORTANT] > This command only works when the page is visible. > -> If the component being hidden/shown is not part of the current page, the command will fail and an error message will be logged. +> If a component being hidden/shown is not part of the current page, the command will fail and an error message will be logged. ### Entity Details Show Service: `entity_details_show` diff --git a/esphome/nspanel_esphome_core.yaml b/esphome/nspanel_esphome_core.yaml index 8f849cf..f980d98 100644 --- a/esphome/nspanel_esphome_core.yaml +++ b/esphome/nspanel_esphome_core.yaml @@ -182,7 +182,7 @@ api: label: string # Main text label for the button. then: - lambda: |- - if (page == current_page->state and not id(is_uploading_tft)) { + if (page == current_page->state and !id(is_uploading_tft)) { disp1->send_command_printf("%spic.picc=%u", id.c_str(), state ? 47 : 46); disp1->send_command_printf("%sbri.picc=%u", id.c_str(), state ? 47 : 46); disp1->send_command_printf("%stext.picc=%u", id.c_str(), state ? 47 : 46); @@ -207,7 +207,7 @@ api: cmd: string # Command string to be sent. Refer to the Nextion Instruction Set for supported commands: https://nextion.tech/instruction-set/ then: - lambda: |- - if (not id(is_uploading_tft)) + if (!id(is_uploading_tft)) disp1->send_command_printf("%s", cmd.c_str()); # Changes the foreground color of a specified component on the display. @@ -217,7 +217,7 @@ api: color: int[] # New color for the component, specified as an RGB array (e.g., [255, 0, 0] for red). then: - lambda: |- - if (not id(is_uploading_tft)) + if (!id(is_uploading_tft)) disp1->set_component_font_color(id.c_str(), esphome::display::ColorUtil::color_to_565(esphome::Color(color[0], color[1], color[2]))); # Updates the text of a specified component on the display. @@ -227,7 +227,7 @@ api: txt: string # New text content to be displayed. Supports both static and dynamic content. then: - lambda: |- - if (not id(is_uploading_tft)) + if (!id(is_uploading_tft)) disp1->set_component_text_printf(id.c_str(), "%s", txt.c_str()); # Updates the value of a specified component on the display. @@ -237,18 +237,21 @@ api: val: int # New integer value to set for the component. Adjust based on the data type you're displaying. then: - lambda: |- - if (not id(is_uploading_tft)) + if (!id(is_uploading_tft)) disp1->set_component_value(id.c_str(), val); # Hides or shows a specified component on the display. - - service: component_visibility + - service: components_visibility variables: - id: string # Identifier of the component to be hidden/shown. Ensure this matches the component's ID in your display layout. + ids: string[] # Identifier of the component to be hidden/shown. Ensure this matches the component's ID in your display layout. visible: bool # Set to true to show the component, or false to hide it. then: - lambda: |- - if (not id(is_uploading_tft)) - set_component_visibility->execute(id.c_str(), visible); + if (!id(is_uploading_tft)) { + for (const std::string& component_id : ids) { + set_component_visibility->execute(component_id.c_str(), visible); + } + } # Displays detailed information for a specific entity. - service: entity_details_show @@ -257,7 +260,7 @@ api: back_page: string # Specifies the page to return to. Accepts "home" or "buttonpage01" to "buttonpage04". then: - lambda: |- - if (not id(is_uploading_tft)) { + if (!id(is_uploading_tft)) { nspanel_ha_blueprint::HomeAssistantEntity entity_id = nspanel_ha_blueprint::extractHomeAssistantEntity(entity); if (entity_id.domain != "invalid" or entity == "embedded_climate") { detailed_entity->publish_state(entity); @@ -291,7 +294,7 @@ api: visible: bool # Set to `true` for visible or `false` for hidden. then: - lambda: |- - if (not id(is_uploading_tft) and not id.empty()) { + if (!id(is_uploading_tft) and !id.empty()) { if (not icon.empty()) disp1->set_component_text_printf(id.c_str(), "%s", icon.c_str()); if (icon_color.size() == 3) disp1->set_component_font_color(id.c_str(), esphome::display::ColorUtil::color_to_565(esphome::Color(icon_color[0], icon_color[1], icon_color[2]))); @@ -349,7 +352,7 @@ api: embedded_indoor_temperature: !lambda return embedded_indoor_temperature; - lambda: |- - if (not id(is_uploading_tft)) { + if (!id(is_uploading_tft)) { using namespace nspanel_ha_blueprint; using namespace esphome::display; @@ -417,7 +420,7 @@ api: outdoor_temp_font: int # Font Id for outdoor temperature indication on the "Home" page. then: - lambda: |- - if (not id(is_uploading_tft)) { + if (!id(is_uploading_tft)) { // Localization id(mui_time_format) = time_format; if (meridiem.size() == 2) { @@ -487,7 +490,7 @@ api: dim: string # Text label for the dim brightness level slider, signaling a lower light option for energy saving. then: - lambda: |- - if (not id(is_uploading_tft)) { + if (!id(is_uploading_tft)) { if (not reboot.empty()) disp1->set_component_text_printf("settings.lbl_reboot", " %s", reboot.c_str()); disp1->set_component_text_printf("settings.lbl_brightness", " %s", brightness.c_str()); display_wrapped_text->execute("settings.lbl_bright", bright.c_str(), display_mode->state == 2 ? 25 : 10); @@ -507,7 +510,7 @@ api: message: string # Detailed message or content of the notification. Include `\r` to insert a line break, allowing for custom formatting. then: - lambda: |- - if (not id(is_uploading_tft)) { + if (!id(is_uploading_tft)) { ESP_LOGV("service.notification_show", "Starting"); goto_page->execute("notification"); @@ -538,7 +541,7 @@ api: then: - lambda: |- // Is page Alarm visible? - if (current_page->state == "alarm" and not id(is_uploading_tft)) // To do: This page constructor should be moved to Blueprint + if (current_page->state == "alarm" and !id(is_uploading_tft)) // To do: This page constructor should be moved to Blueprint { // Update alarm page detailed_entity->publish_state(entity); @@ -637,7 +640,7 @@ api: then: - if: condition: - lambda: return not id(is_uploading_tft); + lambda: return !id(is_uploading_tft); then: - lambda: if (current_page->state == "climate") detailed_entity->publish_state(entity); - script.execute: @@ -671,7 +674,7 @@ api: # https://github.com/home-assistant/core/blob/33ff6b5b6ee3d92f4bb8deb9594d67748ea23d7c/homeassistant/components/media_player/const.py#L23 then: - lambda: |- - if (current_page->state == "media_player" and not id(is_uploading_tft)) { + if (current_page->state == "media_player" and !id(is_uploading_tft)) { detailed_entity->publish_state(entity); disp1->set_component_text_printf("page_label", "%s", friendly_name.c_str()); display_wrapped_text->execute("track", media_title.c_str(), display_mode->state == 2 ? 16 : 27); @@ -809,7 +812,7 @@ api: # Setting this to true keeps the display active during user presence, while false retains the current timer settings. then: - lambda: |- - if (not id(is_uploading_tft)) { + if (!id(is_uploading_tft)) { if (current_page->state == "screensaver") goto_page->execute(wakeup_page_name->state.c_str()); if (reset_timer) timer_reset_all->execute(wakeup_page_name->state.c_str()); @@ -830,7 +833,7 @@ display: - script.execute: setup_sequence on_page: lambda: |- - if (not id(is_uploading_tft)) { + if (!id(is_uploading_tft)) { page_id->update(); if (current_page->state != page_names[x] or x == 9) { current_page->publish_state(page_names[x]); @@ -840,7 +843,7 @@ display: on_touch: lambda: |- - if (not id(is_uploading_tft)) { + if (!id(is_uploading_tft)) { timer_reset_all->execute(page_names[page_id]); switch (page_id) { case 10: // light @@ -1495,7 +1498,7 @@ sensor: on_value: then: - lambda: |- - if (not id(is_uploading_tft) and current_page->state != page_names[x]) { + if (!id(is_uploading_tft) and current_page->state != page_names[x]) { current_page->publish_state(page_names[x]); page_changed->execute(page_names[x]); } @@ -1798,7 +1801,7 @@ script: value: string then: - lambda: |- - if (not id(is_uploading_tft)) { + if (!id(is_uploading_tft)) { if (not embedded) { if (key == "temperature" or key == "target_temp_high" or key == "target_temp_low") ha_call_service->execute("climate.set_temperature", key.c_str(), to_string(stof(value) / 10), detailed_entity->state.c_str()); @@ -1816,7 +1819,7 @@ script: return (compare_versions("${version}", version_tft->state.c_str()) and compare_versions("${version}", id(version_blueprint))); timeout: 60s - lambda: |- - if (not id(is_uploading_tft)) { + if (!id(is_uploading_tft)) { ESP_LOGD("script.check_versions", "Versions:"); ESP_LOGD("script.check_versions", " ESPHome: ${version}"); ESP_LOGD("script.check_versions", " TFT: %s", version_tft->state.c_str()); @@ -2002,7 +2005,7 @@ script: entity: string then: - lambda: |- - if (not id(is_uploading_tft)) { + if (!id(is_uploading_tft)) { if (service != "" and not service.empty()) { auto ha_event = new esphome::api::CustomAPIDevice(); ha_event->fire_homeassistant_event("esphome.nspanel_ha_blueprint", @@ -2035,7 +2038,7 @@ script: mode: restart then: - lambda: |- - if (not id(is_uploading_tft)) { + if (!id(is_uploading_tft)) { notification_label->publish_state(""); notification_text->publish_state(""); notification_unread->turn_off(); @@ -2190,7 +2193,7 @@ script: mode: restart then: - lambda: |- - if (not id(is_uploading_tft)) display_wrapped_text->execute("confirm.title", id(mui_please_confirm_global).c_str(), 15); + if (!id(is_uploading_tft)) display_wrapped_text->execute("confirm.title", id(mui_please_confirm_global).c_str(), 15); - id: page_cover mode: restart @@ -2274,7 +2277,7 @@ script: mode: restart then: - lambda: |- - if (current_page->state == "screensaver" and not id(is_uploading_tft)) { + if (current_page->state == "screensaver" and !id(is_uploading_tft)) { disp1->send_command_printf("back_page_id=%" PRIu8, get_page_id(wakeup_page_name->state.c_str())); if (id(screensaver_display_time)) { disp1->send_command_printf("screensaver.text.font=%i", id(screensaver_display_time_font)); @@ -2370,7 +2373,7 @@ script: mode: restart then: - lambda: |- - if (not id(is_uploading_tft)) { + if (!id(is_uploading_tft)) { switch (int(display_mode->state)) { case 1: // EU model if (id(buttons_settings) & nspanel_ha_blueprint::ButtonSettings::ButtonLeft_Enabled) { // Left button diff --git a/nspanel_blueprint.yaml b/nspanel_blueprint.yaml index c845e15..615c866 100644 --- a/nspanel_blueprint.yaml +++ b/nspanel_blueprint.yaml @@ -3711,7 +3711,7 @@ variables: color: 'esphome.{{ nspanel_name }}_component_color' text: 'esphome.{{ nspanel_name }}_component_text' value: 'esphome.{{ nspanel_name }}_component_val' - visibility: 'esphome.{{ nspanel_name }}_component_visibility' + visibility: 'esphome.{{ nspanel_name }}_components_visibility' entity_details_show: 'esphome.{{ nspanel_name }}_entity_details_show' hw_button_state: 'esphome.{{ nspanel_name }}_hw_button_state' icon: 'esphome.{{ nspanel_name }}_icon' @@ -3856,7 +3856,7 @@ variables: unknown: 1 unavailable: 1 - page: + pages: current: '{{ states(currentpage) }}' home: "home" weatherpages: @@ -7535,7 +7535,7 @@ condition: - '{{ device_name_sensor is defined and device_name_sensor is string and has_value(device_name_sensor) and states(device_name_sensor) | default("") is string }}' - condition: or # Update page Home only when visible or home_page_background_update is enabled conditions: - - '{{ home_page_background_update or page.current == page.home }}' + - '{{ home_page_background_update or pages.current == pages.home }}' - '{{ trigger.id not in ["home_value01_state", "home_value02_state", "home_value03_state"] }}' - condition: or # Do not update with indoor temp changes when embedded indoor temp is used conditions: @@ -7543,7 +7543,7 @@ condition: conditions: - condition: trigger id: indoortemp_state - - '{{ (home_page_background_update or page.current == page.home ) and not embedded_indoor_temperature }}' + - '{{ (home_page_background_update or pages.current == pages.home ) and not embedded_indoor_temperature }}' - condition: or # Do not update component if state haven't changed (ignore attributes changed) - event based triggers conditions: - condition: not @@ -7552,13 +7552,13 @@ condition: id: home_custom_buttons - condition: and conditions: - - '{{ home_page_background_update or page.current == page.home }}' + - '{{ home_page_background_update or pages.current == pages.home }}' - '{{ trigger.event is defined and trigger.event.data is defined }}' - '{{ trigger.event.data.entity_id is defined }}' - '{{ trigger.event.data.entity_id is not match "media_player." }}' - condition: and conditions: - - '{{ home_page_background_update or page.current == page.home }}' + - '{{ home_page_background_update or pages.current == pages.home }}' - '{{ trigger.event is defined and trigger.event.data is defined }}' - '{{ trigger.event.data.new_state is defined and trigger.event.data.new_state.state is defined }}' - '{{ trigger.event.data.old_state is defined and trigger.event.data.old_state.state is defined }}' @@ -7573,7 +7573,7 @@ condition: - trigger_entitypage02 - trigger_entitypage03 - trigger_entitypage04 - - '{{ page.current in page.entitypages }}' + - '{{ pages.current in pages.entitypages }}' - condition: or # Do not update values when page climate is not visible conditions: - condition: not @@ -7586,7 +7586,7 @@ condition: - climate_value04_state - climate_button08_state - climate_button09_state - - '{{ page.current == page.climate }}' + - '{{ pages.current == pages.climate }}' - condition: or # Do not update values when page button is not visible conditions: - condition: not @@ -7625,8 +7625,8 @@ condition: - current_state_entity30 - current_state_entity31 - current_state_entity32 - - '{{ page.current in page.buttonpages }}' - - '{{ page.current in [page.light, page.cover, page.climate, page.fan, page.alarm] and trigger.entity_id is defined and trigger.entity_id == states(detailed_entity) }}' + - '{{ pages.current in pages.buttonpages }}' + - '{{ pages.current in [pages.light, pages.cover, pages.climate, pages.fan, pages.alarm] and trigger.entity_id is defined and trigger.entity_id == states(detailed_entity) }}' ############################################################# ##### START - Action ##### @@ -8014,7 +8014,7 @@ action: continue_on_error: true - repeat: # Disable empty buttons pages - for_each: '{{ page.buttonpages }}' + for_each: '{{ pages.buttonpages }}' sequence: - service: '{{ nspanel.service.command }}' data: @@ -8034,7 +8034,7 @@ action: continue_on_error: true - repeat: # Disable empty entity pages - for_each: '{{ page.entitypages }}' + for_each: '{{ pages.entitypages }}' sequence: - service: '{{ nspanel.service.command }}' data: @@ -8171,7 +8171,7 @@ action: - choose: ## PAGE HOME ## - alias: Home page - conditions: '{{ nspanel_event.page == page.home }}' + conditions: '{{ nspanel_event.page == pages.home }}' sequence: &refresh_page_home ##### Weather Icon Home Page ##### @@ -8317,11 +8317,11 @@ action: visible: true continue_on_error: true else: - - if: '{{ page.current == page.home }}' + - if: '{{ pages.current == pages.home }}' then: - service: '{{ nspanel.service.component.visibility }}' data: - id: '{{ repeat.item.component }}' + ids: '{{ [ repeat.item.component ] }}' visible: false continue_on_error: true @@ -8431,7 +8431,7 @@ action: - &hide-home_page-status_bar_chip service: '{{ nspanel.service.component.visibility }}' data: - id: 'home.{{ repeat.item.component }}' + ids: '{{ [ "home." ~ repeat.item.component ] }}' visible: false continue_on_error: true else: @@ -8514,11 +8514,11 @@ action: ## BUTTON PAGES 01 - 04 ## - alias: Button pages - conditions: '{{ nspanel_event.page in page.buttonpages }}' + conditions: '{{ nspanel_event.page in pages.buttonpages }}' sequence: &refresh_page_buttonpage - &variables_page_buttons variables: - event_page: '{{ nspanel_event.page if nspanel_event is defined and nspanel_event.page is defined else page.current }}' + event_page: '{{ nspanel_event.page if nspanel_event is defined and nspanel_event.page is defined else pages.current }}' button_pages_icon_size: !input button_pages_icon_size ##### BUTTON Page Labels ##### confirm_list: > @@ -8539,7 +8539,7 @@ action: {% set ns.index = ns.index + 1 %} {% endfor %} {{ ns.decimal_value }} - - if: '{{ event_page in page.buttonpages }}' + - if: '{{ event_page in pages.buttonpages }}' then: ##### Button page Label ##### - if: '{{ buttons_pages.labels[event_page] | length > 0 }}' @@ -8631,7 +8631,7 @@ action: ## PAGE LIGHT ## - alias: Light settings page - conditions: '{{ nspanel_event.page == page.light }}' + conditions: '{{ nspanel_event.page == pages.light }}' sequence: &refresh_page_light - variables: light_entity: > @@ -8714,17 +8714,7 @@ action: continue_on_error: true - service: '{{ nspanel.service.component.visibility }}' data: - id: temp_button - visible: true - continue_on_error: true - - service: '{{ nspanel.service.component.visibility }}' - data: - id: temp_value_2 - visible: true - continue_on_error: true - - service: '{{ nspanel.service.component.visibility }}' - data: - id: temp_touch + ids: [ "temp_button", "temp_value_2", "temp_touch" ] visible: true continue_on_error: true @@ -8733,18 +8723,13 @@ action: then: - service: '{{ nspanel.service.component.visibility }}' data: - id: color_button - visible: true - continue_on_error: true - - service: '{{ nspanel.service.component.visibility }}' - data: - id: color_touch + ids: [ "color_button", "color_touch" ] visible: true continue_on_error: true ## PAGE COVER ## - alias: Cover settings page - conditions: '{{ nspanel_event.page == page.cover }}' + conditions: '{{ nspanel_event.page == pages.cover }}' sequence: &refresh_page_cover - variables: cover_entity: > @@ -8862,7 +8847,7 @@ action: ## PAGE FAN ## - alias: Fan settings page - conditions: '{{ nspanel_event.page == page.fan }}' + conditions: '{{ nspanel_event.page == pages.fan }}' sequence: &refresh_page_fan - variables: fan_entity: > @@ -8895,7 +8880,7 @@ action: continue_on_error: true - service: '{{ nspanel.service.component.visibility }}' data: - id: fan.bt_oscillate + ids: [ "fan.bt_oscillate" ] visible: true continue_on_error: true - condition: '{{ fan.steps > 0 and fan.supported_features | bitwise_and(1) > 0 }}' # Set speed @@ -8931,7 +8916,7 @@ action: ## PAGE MEDIA PLAYER ## - alias: Media player settings page - conditions: '{{ nspanel_event.page == page.media_player }}' + conditions: '{{ nspanel_event.page == pages.media_player }}' sequence: &refresh_page_media_player - variables: media_player_entity: > @@ -8967,7 +8952,7 @@ action: if (state_attr(media_player_entity, "mass_player_type") | default("")) == "group" else state_attr(media_player_entity, "supported_features") | int(0) }} - - service: '{{ nspanel.service.page.media_player }}' + - service: '{{ nspanel.service.pages.media_player }}' data: entity: '{{ media_player_entity }}' state: '{{ media_player.state if media_player.state is string else "" }}' @@ -9006,7 +8991,7 @@ action: }} supported_features: '{{ media_player.supported_features }}' continue_on_error: true - - wait_template: '{{ states(currentpage) != page.media_player }}' + - wait_template: '{{ states(currentpage) != pages.media_player }}' timeout: milliseconds: '{{ media_player_update_interval }}' continue_on_timeout: true @@ -9015,12 +9000,12 @@ action: until: - or: - '{{ wait_completed }}' - - '{{ states(currentpage) != page.media_player }}' # Don't replace this by page.current as this have to be evaluated all the time + - '{{ states(currentpage) != pages.media_player }}' # Don't replace this by pages.current as this have to be evaluated all the time - '{{ nspanel_event.type != "page_changed" }}' ## PAGE ALARM ## - alias: Alarm settings page - conditions: '{{ nspanel_event.page == page.alarm }}' + conditions: '{{ nspanel_event.page == pages.alarm }}' sequence: &refresh_page_alarm - variables: alarm_entity_temp: > @@ -9046,7 +9031,7 @@ action: alarm: code_format: '{{ state_attr(entity_id, "code_format") }}' code_arm_required: '{{ state_attr(entity_id, "code_arm_required") | default(true) }}' - - service: '{{ nspanel.service.page.alarm }}' + - service: '{{ nspanel.service.pages.alarm }}' data: page_title: '{{ entity.name }}' state: '{{ entity_state }}' @@ -9059,7 +9044,7 @@ action: ## PAGE CLIMATE ## - alias: Climate page - conditions: '{{ nspanel_event.page == page.climate }}' + conditions: '{{ nspanel_event.page == pages.climate }}' sequence: &refresh_page_climate - &variables_climate_entity variables: @@ -9172,7 +9157,7 @@ action: {% elif "idle" in climate_action %}{{ all_icons.thermometer }} {% else %}{{ all_icons.blank }} {% endif %} - - service: '{{ nspanel.service.page.climate }}' + - service: '{{ nspanel.service.pages.climate }}' data: current_temp: '{{ current_temp }}' supported_features: '{{ supported_features }}' @@ -9215,7 +9200,7 @@ action: ### Enable button click ### - service: '{{ nspanel.service.component.visibility }}' data: - id: '{{ repeat.item.component }}' + ids: '{{ [ repeat.item.component ] }}' visible: true continue_on_error: true @@ -9260,17 +9245,17 @@ action: ### Enable button click ### - service: '{{ nspanel.service.component.visibility }}' data: - id: '{{ repeat.item.component }}' + ids: '{{ [ repeat.item.component ] }}' visible: true continue_on_error: true ## ENTITY PAGES 01 - 04 ## - alias: Entity pages - conditions: '{{ nspanel_event.page in page.entitypages }}' + conditions: '{{ nspanel_event.page in pages.entitypages }}' sequence: &refresh_entity_pages - &variables-entity_pages variables: - event_page: '{{ nspanel_event.page if nspanel_event is defined and nspanel_event.page is defined else page.current }}' + event_page: '{{ nspanel_event.page if nspanel_event is defined and nspanel_event.page is defined else pages.current }}' ##### Entity page - Label ##### - if: '{{ entities_pages.labels[event_page] | length > 0 }}' then: @@ -9320,7 +9305,7 @@ action: ## PAGE WEATHER (WEATHER01 to WEATHER05) ## - alias: Weather pages - conditions: '{{ nspanel_event.page in page.weatherpages }}' + conditions: '{{ nspanel_event.page in pages.weatherpages }}' sequence: - variables: weather_attribution: '{{ state_attr(weather_entity, "attribution") if weather_entity is string }}' @@ -9778,7 +9763,7 @@ action: cmd: > {{ page_name }}.weather_icon.pic={{ nextion.pic.weather[states(weather_entity) | default("unavailable") if weather_entity is string else "unavailable"] | int(1) - if condition == "unknown" and page_name == page.weatherpages[0] + if condition == "unknown" and page_name == pages.weatherpages[0] else nextion.pic.weather[condition] | int(1) }} continue_on_error: true @@ -9819,6 +9804,43 @@ action: continue_on_error: true else: *forecast_unavailable + ## PAGE UTILITIES ## + # groups: + # - name: home + # label: !input utilities_page01_home_label + # icon: !input utilities_page01_home_icon + # value1: !input utilities_page01_home_value1 + # value2: !input utilities_page01_home_value2 + # color: !input utilities_page01_home_color + - alias: Utilities page + conditions: '{{ nspanel_event.page in pages.utilities }}' + sequence: &refresh_page_utilities + ## Page title + - variables: + page_icon: '{{ pages_utilities.title.icon.split("mdi:")[1] if pages_utilities.title.icon is string and pages_utilities.title.icon.split("mdi:") | count == 2 }}' + - service: '{{ nspanel.service.value }}' + data: + id: utilities.title + icon: '{{ all_icons[page_icon] if page_icon in all_icons else all_icons.flash }}' + icon_color: [] + name: '' + value: '{{ pages_utilities.title.label }}' + value_color: [] + continue_on_error: true + ## Groups + - repeat: + for_each: '{{ pages_utilities.groups | list }}' + sequence: &refresh_page_utilities_group + - if: '{{ repeat.item.icon is defined and repeat.item.icon is string and repeat.item.icon.split("mdi:") | count == 2 }}' + then: + - service: '{{ nspanel.service.component.text }}' + else: + - service: '{{ nspanel.service.component.visibility }}' + data: + ids: '{{ [ repeat.item.name, repeat.item.name ~ "_value2", repeat.item.name ~ "_icon", repeat.item.name ~ "_label", repeat.item.name ~ "_line" ] }}' + visible: false + continue_on_error: true + ##### Button click ##### - alias: Button click conditions: @@ -9846,7 +9868,7 @@ action: - '{{ entity_domain in ["alarm_control_panel", "climate", "cover", "light", "fan", "media_player"] }}' sequence: - variables: - back_page: '{{ page.home }}' + back_page: '{{ pages.home }}' - &entity_details_show service: '{{ nspanel.service.entity_details_show }}' data: @@ -9901,7 +9923,7 @@ action: - alias: Buttons pages conditions: - - '{{ nspanel_event.page in page.buttonpages }}' + - '{{ nspanel_event.page in pages.buttonpages }}' sequence: - *variables_page_buttons - variables: @@ -9942,7 +9964,7 @@ action: - alias: Climate page conditions: - - '{{ nspanel_event.page == page.climate }}' + - '{{ nspanel_event.page == pages.climate }}' sequence: - *climate-update_custom_buttons-variables - variables: @@ -9977,7 +9999,7 @@ action: - *short_press-service_call - alias: Home page custom buttons conditions: - - '{{ nspanel_event.page == page.home }}' + - '{{ nspanel_event.page == pages.home }}' sequence: - *variables_home_page_custom_buttons - variables: @@ -9994,7 +10016,7 @@ action: - '{{ entity_domain in ["alarm_control_panel", "climate", "cover", "fan", "light", "media_player"] }}' then: - variables: - back_page: '{{ page.home }}' + back_page: '{{ pages.home }}' - *entity_details_show else: - *short_press-service_call @@ -10066,7 +10088,7 @@ action: - choose: - alias: light settings # rgb_color, brightness, color_temp - This was kept until we find a solution to call with rgb_color directly from ESPHome conditions: - - '{{ nspanel_event.page == page.light }}' + - '{{ nspanel_event.page == pages.light }}' - '{{ nspanel_event.component in ["rgb_color", "brightness_pct", "color_temp"] }}' - '{{ nspanel_event.entity is defined and nspanel_event.entity is string and nspanel_event.entity | length > 0 }}' sequence: @@ -10078,20 +10100,20 @@ action: - alias: Jump to climate page conditions: - - '{{ nspanel_event.page == page.home }} ' + - '{{ nspanel_event.page == pages.home }} ' - '{{ nspanel_event.component == "climate" }}' - '{{ nspanel_event.value == "release" }}' - '{{ climate | length > 0 }} ' sequence: - variables: entity_id: '{{ climate }}' - back_page: '{{ page.home }}' + back_page: '{{ pages.home }}' - *variable_entity - *entity_details_show - alias: Show button - Notification clear conditions: - - '{{ nspanel_event.page == page.notification }}' + - '{{ nspanel_event.page == pages.notification }}' - '{{ nspanel_event.component == "clear" }}' sequence: - service: switch.turn_off @@ -10100,12 +10122,12 @@ action: continue_on_error: true - service: '{{ nspanel.service.command }}' data: - cmd: 'page {{ page.home }}' + cmd: 'page {{ pages.home }}' continue_on_error: true - alias: Show button - Notification accept conditions: - - '{{ nspanel_event.page == page.notification }}' + - '{{ nspanel_event.page == pages.notification }}' - '{{ nspanel_event.component == "accept" }}' sequence: - service: switch.turn_off @@ -10117,7 +10139,7 @@ action: continue_on_error: true - service: '{{ nspanel.service.command }}' data: - cmd: 'page {{ page.home }}' + cmd: 'page {{ pages.home }}' continue_on_error: true ##### BOOT NSPANEL - automation reload ##### @@ -10170,15 +10192,15 @@ action: - choose: ## PAGE HOME ## - - conditions: '{{ page.current == page.home }}' + - conditions: '{{ pages.current == pages.home }}' sequence: *refresh_page_home ## PAGE BUTTON PAGES 01 - 04 ## - - conditions: '{{ page.current in page.buttonpages }}' + - conditions: '{{ pages.current in pages.buttonpages }}' sequence: *refresh_page_buttonpage ## ENTITY PAGES ## - - conditions: '{{ page.current in page.entitypages }}' + - conditions: '{{ pages.current in pages.entitypages }}' sequence: *refresh_entity_pages ##### UPDATE BUTTONS PAGES - button page / light page / cover page ##### @@ -10221,13 +10243,13 @@ action: - '{{ trigger.to_state.state not in enum.states.unknown }}' - condition: or conditions: - - '{{ page.current in page.buttonpages }}' - - '{{ page.current in [page.light, page.cover, page.climate, page.fan, page.alarm] and trigger.entity_id == states(detailed_entity) }}' + - '{{ pages.current in pages.buttonpages }}' + - '{{ pages.current in [pages.light, pages.cover, pages.climate, pages.fan, pages.alarm] and trigger.entity_id == states(detailed_entity) }}' sequence: - choose: - alias: Button pages conditions: - - '{{ page.current in page.buttonpages }}' + - '{{ pages.current in pages.buttonpages }}' sequence: - *variables_page_buttons - repeat: @@ -10235,7 +10257,7 @@ action: {{ buttons_pages.buttons | selectattr("page", "defined") - | selectattr("page", "eq", page.current) + | selectattr("page", "eq", pages.current) | selectattr("entity", "defined") | selectattr("entity", "eq", trigger.entity_id) | list @@ -10243,37 +10265,37 @@ action: sequence: *display_button_page_button - alias: 'Light settings page' conditions: - - '{{ page.current == page.light }}' + - '{{ pages.current == pages.light }}' - '{{ trigger.entity_id is match "light." }}' - '{{ trigger.entity_id == states(detailed_entity) }}' sequence: *refresh_page_light - alias: 'Cover settings page' conditions: - - '{{ page.current == page.cover }}' + - '{{ pages.current == pages.cover }}' - '{{ trigger.entity_id is match "cover." }}' - '{{ trigger.entity_id == states(detailed_entity) }}' sequence: *refresh_page_cover - alias: 'Climate page' conditions: - - '{{ page.current == page.climate }}' + - '{{ pages.current == pages.climate }}' - '{{ trigger.entity_id is match "climate." }}' - '{{ trigger.entity_id == states(detailed_entity) }}' sequence: *refresh_page_climate - alias: 'Fan page' conditions: - - '{{ page.current == page.fan }}' + - '{{ pages.current == pages.fan }}' - '{{ trigger.entity_id is match "fan." }}' - '{{ trigger.entity_id == states(detailed_entity) }}' sequence: *refresh_page_fan - alias: 'Media player page' conditions: - - '{{ page.current == page.media_player }}' + - '{{ pages.current == pages.media_player }}' - '{{ trigger.entity_id is match "media_player." }}' - '{{ trigger.entity_id == states(detailed_entity) }}' sequence: *refresh_page_media_player - alias: 'Alarm page' conditions: - - '{{ page.current == page.alarm }}' + - '{{ pages.current == pages.alarm }}' - '{{ trigger.entity_id is match "alarm_control_panel." }}' - '{{ trigger.entity_id == states(detailed_entity) }}' sequence: *refresh_page_alarm @@ -10287,7 +10309,7 @@ action: - trigger_entitypage02 - trigger_entitypage03 - trigger_entitypage04 - - '{{ page.current in page.entitypages }}' + - '{{ pages.current in pages.entitypages }}' sequence: - *variables-entity_pages - repeat: @@ -10295,7 +10317,7 @@ action: {{ entities_pages.entities | selectattr("page", "defined") - | selectattr("page", "eq", page.current) + | selectattr("page", "eq", pages.current) | selectattr("entity", "defined") | selectattr("entity", "eq", trigger.entity_id) | list @@ -10311,7 +10333,7 @@ action: - climate_value02_state - climate_value03_state - climate_value04_state - - '{{ page.current == page.climate }}' + - '{{ pages.current == pages.climate }}' sequence: - *variables-climate_page - repeat: @@ -10331,7 +10353,7 @@ action: id: - climate_button08_state - climate_button09_state - - '{{ page.current == page.climate }}' + - '{{ pages.current == pages.climate }}' sequence: - *climate-update_custom_buttons @@ -10344,7 +10366,7 @@ action: - *update-home_page-climate_chip - if: - '{{ trigger.event.data.new_state.state not in enum.states.unknown }}' - - '{{ page.current == page.climate }}' + - '{{ pages.current == pages.climate }}' - '{{ trigger.event.data.entity_id == states(detailed_entity) }}' then: - variables: @@ -10367,7 +10389,7 @@ action: - choose: - alias: "Home page" conditions: - - '{{ page.current in page.home }}' + - '{{ pages.current in pages.home }}' sequence: - *variables_home_page_custom_buttons - repeat: @@ -10376,37 +10398,37 @@ action: - *display_home_page_custom_buttons - alias: 'Light settings page' conditions: - - '{{ page.current == page.light }}' + - '{{ pages.current == pages.light }}' - '{{ trigger_entity_id is match "light." }}' - '{{ trigger_entity_id == states(detailed_entity) }}' sequence: *refresh_page_light - alias: 'Cover settings page' conditions: - - '{{ page.current == page.cover }}' + - '{{ pages.current == pages.cover }}' - '{{ trigger_entity_id is match "cover." }}' - '{{ trigger_entity_id == states(detailed_entity) }}' sequence: *refresh_page_cover - alias: 'Climate page' conditions: - - '{{ page.current == page.climate }}' + - '{{ pages.current == pages.climate }}' - '{{ trigger_entity_id is match "climate." }}' - '{{ trigger_entity_id == states(detailed_entity) }}' sequence: *refresh_page_climate - alias: 'Fan page' conditions: - - '{{ page.current == page.fan }}' + - '{{ pages.current == pages.fan }}' - '{{ trigger_entity_id is match "fan." }}' - '{{ trigger_entity_id == states(detailed_entity) }}' sequence: *refresh_page_fan - alias: 'Media player page' conditions: - - '{{ page.current == page.media_player }}' + - '{{ pages.current == pages.media_player }}' - '{{ trigger_entity_id is match "media_player." }}' - '{{ trigger_entity_id == states(detailed_entity) }}' sequence: *refresh_page_media_player - alias: 'Alarm page' conditions: - - '{{ page.current == page.alarm }}' + - '{{ pages.current == pages.alarm }}' - '{{ trigger_entity_id is match "alarm_control_panel." }}' - '{{ trigger_entity_id == states(detailed_entity) }}' sequence: *refresh_page_alarm @@ -10419,7 +10441,7 @@ action: - home_value01_state - home_value02_state - home_value03_state - - '{{ page.current == page.home }}' + - '{{ pages.current == pages.home }}' sequence: - *variables-home_page_values - repeat: @@ -10488,7 +10510,7 @@ action: conditions: - condition: trigger id: weather_state_change - - '{{ page.current == page.home and trigger.event.data.new_state.state not in enum.states.unknown }}' + - '{{ pages.current == pages.home and trigger.event.data.new_state.state not in enum.states.unknown }}' sequence: - *refresh-page_home-outdoor_temp - *refresh-page_home-weather_pic