From 6356f34a263d1c126a7130e03299d33ab82006dd Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 20 Nov 2024 15:24:39 +0100 Subject: [PATCH] yamllint --- .../nspanel_ha_blueprint/ha_to_nextion.h | 8 +- components/nspanel_ha_blueprint/icons.h | 2 +- esphome/nspanel_esphome_core_base.yaml | 2 +- esphome/nspanel_esphome_core_hw_wifi.yaml | 21 +- .../nspanel_esphome_core_page_buttons.yaml | 2 +- nspanel_blueprint.yaml | 1612 ++++++++++++++--- 6 files changed, 1335 insertions(+), 312 deletions(-) diff --git a/components/nspanel_ha_blueprint/ha_to_nextion.h b/components/nspanel_ha_blueprint/ha_to_nextion.h index 55185684..cbe000f1 100644 --- a/components/nspanel_ha_blueprint/ha_to_nextion.h +++ b/components/nspanel_ha_blueprint/ha_to_nextion.h @@ -32,11 +32,11 @@ namespace nspanel_ha_blueprint { void addSubscription(const std::string &entity_id, const std::string &page, const std::string &component, bool is_global) { esphome::ESP_LOGD(TAG_HA_TO_NEXTION, "New subscription requested to '%s', page '%s', and component '%s'", - entity_id.c_str(), page.c_str(), component.c_str()); + entity_id.c_str(), page.c_str(), component.c_str()); // Check if subscription already exists if (findSubscription(page, component) != nullptr) { esphome::ESP_LOGW(TAG_HA_TO_NEXTION, "Subscription for page '%s', and component '%s' already exists!", - page.c_str(), component.c_str()); + page.c_str(), component.c_str()); return; } esphome::ESP_LOGD(TAG_HA_TO_NEXTION, "No previous subscription found"); @@ -155,10 +155,10 @@ namespace nspanel_ha_blueprint { void updateNextionDisplay(EntityTarget* subscription, const std::string &state) { // Placeholder: Replace with actual logic to send data to the Nextion display if (subscription->is_global) { - esphome::ESP_LOGI(TAG_HA_TO_NEXTION, "Global Component: Sending update to Nextion for entity '%s' with value: %s", + esphome::ESP_LOGD(TAG_HA_TO_NEXTION, "Global Component: Sending update to Nextion for entity '%s' with value: %s", subscription->entity_id, state.c_str()); } else { - esphome::ESP_LOGI(TAG_HA_TO_NEXTION, "Component '%s' on page '%s': Sending update to Nextion with value: %s", + esphome::ESP_LOGD(TAG_HA_TO_NEXTION, "Component '%s' on page '%s': Sending update to Nextion with value: %s", subscription->component, subscription->page, state.c_str()); } diff --git a/components/nspanel_ha_blueprint/icons.h b/components/nspanel_ha_blueprint/icons.h index bd2f18a8..a091ed72 100644 --- a/components/nspanel_ha_blueprint/icons.h +++ b/components/nspanel_ha_blueprint/icons.h @@ -100,7 +100,7 @@ namespace nspanel_ha_blueprint { PageIcon* new_icon = icon_allocator.allocate(1); // Allocate memory for 1 PageIcon in PSRAM if (!new_icon) { - esphome::ESP_LOGE(TAG_ICONS, "Failed to allocate memory for new icon."); + esphome::ESP_LOGE(TAG_ICONS, "Failed to allocate memory for new icon %s on page %s", component, page); return nullptr; // Memory allocation failed } diff --git a/esphome/nspanel_esphome_core_base.yaml b/esphome/nspanel_esphome_core_base.yaml index b0069612..fe9f982a 100644 --- a/esphome/nspanel_esphome_core_base.yaml +++ b/esphome/nspanel_esphome_core_base.yaml @@ -191,7 +191,7 @@ script: - id: dump_config mode: restart then: - - delay: 30s + - delay: 90s - lambda: |- static const char *const TAG = "${project_tag}"; // report API status diff --git a/esphome/nspanel_esphome_core_hw_wifi.yaml b/esphome/nspanel_esphome_core_hw_wifi.yaml index 495f428c..73fc7f9b 100644 --- a/esphome/nspanel_esphome_core_hw_wifi.yaml +++ b/esphome/nspanel_esphome_core_hw_wifi.yaml @@ -98,11 +98,17 @@ script: mode: restart then: - lambda: |- + static const char* TAG = "script.refresh_wifi_icon"; + ESP_LOGV(TAG, "Refreshing Wi-Fi icon"); static PageIcon* wifi_icon = get_icon("home", "wifi_icon"); - if (!wifi_icon or wifi_icon == nullptr) + if (!wifi_icon or wifi_icon == nullptr) { + ESP_LOGE(TAG, "No icon pointer available"); return; - if (!wifi_icon->initiated) + } + if (!wifi_icon->initiated){ + ESP_LOGV(TAG, "Initializing icon"); wifi_icon->initiated = true; + } static bool blueprint_is_connected = false; static bool api_is_connected = false; static bool wifi_is_connected = false; @@ -111,6 +117,7 @@ script: wifi_is_connected != wifi_component->is_connected() or api_is_connected != api_server->is_connected(); if (status_has_changed) { + ESP_LOGV(TAG, "Status has changed"); blueprint_is_connected = is_boot_step_completed(${BOOT_STEP_VERSIONING}); api_is_connected = api_server->is_connected(); wifi_is_connected = wifi_component->is_connected(); @@ -136,11 +143,10 @@ script: icon_set_icon->execute(wifi_icon); } if (blueprint_is_connected and api_is_connected and wifi_is_connected) { - ESP_LOGI("script.refresh_wifi_icon", "Wi-Fi icon changed to %s (\\u%04X)", - new_wifi_icon, decode_utf8(new_wifi_icon)); + ESP_LOGI(TAG, "Wi-Fi icon changed to %s (\\u%04X)", new_wifi_icon, decode_utf8(new_wifi_icon)); set_variable_value->execute("api", 1); } else { - ESP_LOGW("script.refresh_wifi_icon", "Wi-Fi icon changed to %s (\\u%04X)", + ESP_LOGW(TAG, "Wi-Fi icon changed to %s (\\u%04X)", new_wifi_icon, decode_utf8(new_wifi_icon)); set_variable_value->execute("api", 0); } @@ -148,14 +154,17 @@ script: // Update Wi-Fi icon color if (status_has_changed or (wifi_rssi_warning != (wifi_rssi->state <= -70))) { + ESP_LOGV(TAG, "RSSI changed"); wifi_rssi_warning = (wifi_rssi->state <= -70); uint16_t new_wifi_icon_color = (blueprint_is_connected and wifi_is_connected and api_is_connected) ? (wifi_rssi_warning ? 64992 : 33808) : 63488; if (wifi_icon->icon_color != new_wifi_icon_color) { wifi_icon->icon_color = new_wifi_icon_color; - if (id(current_page_id) == ${PAGE_ID_HOME}) + if (id(current_page_id) == ${PAGE_ID_HOME}) { + ESP_LOGD(TAG, "Wi-Fi icon color changed to %" PRIu16, new_wifi_icon_color); icon_set_color->execute(wifi_icon); + } } } diff --git a/esphome/nspanel_esphome_core_page_buttons.yaml b/esphome/nspanel_esphome_core_page_buttons.yaml index 59fc803d..ab488ae6 100644 --- a/esphome/nspanel_esphome_core_page_buttons.yaml +++ b/esphome/nspanel_esphome_core_page_buttons.yaml @@ -33,7 +33,7 @@ api: label: string # Main text label for the button. then: - lambda: |- - ESP_LOGI("api.actions.button", "Received data for button %i", id); + ESP_LOGD("api.actions.button", "Received data for button %i", id); if (id >= 1 and id <= 32) { uint8_t index = static_cast(id) - 1; bool changed_visibility = !buttonpage_buttons[index].visible; diff --git a/nspanel_blueprint.yaml b/nspanel_blueprint.yaml index 09cf81ea..619c118b 100644 --- a/nspanel_blueprint.yaml +++ b/nspanel_blueprint.yaml @@ -3797,7 +3797,14 @@ trigger_variables: nspanel_entities: '{{ device_entities(nspanel_deviceid) }}' device_name: > {%- if nspanel_entities | count > 0 %} - {{ (nspanel_entities | selectattr(None, "search", "_nextion_display") | list | first).split(".")[1].split("_nextion_display")[0] }} + {{ + ( + nspanel_entities + | selectattr(None, "search", "_nextion_display") + | list + | first + ).split(".")[1].split("_nextion_display")[0] + }} {%- elif nspanel_deviceid is string %} {{ nspanel_deviceid | regex_replace("[^a-zA-Z0-9]", "_") | regex_replace("_+", "_") | lower }} {%- endif %} @@ -3917,7 +3924,7 @@ variables: triggers: - triggers: # General - - id: nspanel_event # Panel Event - This is the new main event handler introduced on v4.0 to get info from the panel + - id: nspanel_event # Panel Event - Main event handler introduced on v4.0 to get info from the panel trigger: event event_type: esphome.nspanel_ha_blueprint event_data: @@ -4388,7 +4395,11 @@ triggers: - trigger: template value_template: > {% set line_ref_id = utilities_line_reference.page01.main %} - {% set line_ref_state = (states(line_ref_id) | float(0)) if line_ref_id is string and line_ref_id.split(".") == 2 else 0 %} + {% set line_ref_state = + (states(line_ref_id) | float(0)) + if line_ref_id is string and line_ref_id.split(".") == 2 + else 0 + %} {{ ((line_ref_state > 0) - (line_ref_state < 0)) }} id: utilities_page for: @@ -4429,7 +4440,11 @@ triggers: - trigger: template value_template: > {% set line_ref_id = utilities_line_reference.page01.group01 %} - {% set line_ref_state = (states(line_ref_id) | float(0)) if line_ref_id is string and line_ref_id.split(".") == 2 else 0 %} + {% set line_ref_state = + (states(line_ref_id) | float(0)) + if line_ref_id is string and line_ref_id.split(".") == 2 + else 0 + %} {{ ((line_ref_state > 0) - (line_ref_state < 0)) }} id: utilities_page for: @@ -4448,7 +4463,11 @@ triggers: - trigger: template value_template: > {% set line_ref_id = utilities_line_reference.page01.group02 %} - {% set line_ref_state = (states(line_ref_id) | float(0)) if line_ref_id is string and line_ref_id.split(".") == 2 else 0 %} + {% set line_ref_state = + (states(line_ref_id) | float(0)) + if line_ref_id is string and line_ref_id.split(".") == 2 + else 0 + %} {{ ((line_ref_state > 0) - (line_ref_state < 0)) }} id: utilities_page for: @@ -4467,7 +4486,11 @@ triggers: - trigger: template value_template: > {% set line_ref_id = utilities_line_reference.page01.group03 %} - {% set line_ref_state = (states(line_ref_id) | float(0)) if line_ref_id is string and line_ref_id.split(".") == 2 else 0 %} + {% set line_ref_state = + (states(line_ref_id) | float(0)) + if line_ref_id is string and line_ref_id.split(".") == 2 + else 0 + %} {{ ((line_ref_state > 0) - (line_ref_state < 0)) }} id: utilities_page for: @@ -4486,7 +4509,11 @@ triggers: - trigger: template value_template: > {% set line_ref_id = utilities_line_reference.page01.group04 %} - {% set line_ref_state = (states(line_ref_id) | float(0)) if line_ref_id is string and line_ref_id.split(".") == 2 else 0 %} + {% set line_ref_state = + (states(line_ref_id) | float(0)) + if line_ref_id is string and line_ref_id.split(".") == 2 + else 0 + %} {{ ((line_ref_state > 0) - (line_ref_state < 0)) }} id: utilities_page for: @@ -4505,7 +4532,11 @@ triggers: - trigger: template value_template: > {% set line_ref_id = utilities_line_reference.page01.group05 %} - {% set line_ref_state = (states(line_ref_id) | float(0)) if line_ref_id is string and line_ref_id.split(".") == 2 else 0 %} + {% set line_ref_state = + (states(line_ref_id) | float(0)) + if line_ref_id is string and line_ref_id.split(".") == 2 + else 0 + %} {{ ((line_ref_state > 0) - (line_ref_state < 0)) }} id: utilities_page for: @@ -4524,7 +4555,11 @@ triggers: - trigger: template value_template: > {% set line_ref_id = utilities_line_reference.page01.group06 %} - {% set line_ref_state = (states(line_ref_id) | float(0)) if line_ref_id is string and line_ref_id.split(".") == 2 else 0 %} + {% set line_ref_state = + (states(line_ref_id) | float(0)) + if line_ref_id is string and line_ref_id.split(".") == 2 + else 0 + %} {{ ((line_ref_state > 0) - (line_ref_state < 0)) }} id: utilities_page for: @@ -8026,14 +8061,55 @@ actions: DRY: 32 FAN_ONLY: 64 states: - "on": ["on", "open", "opening", "true", "True", true, True, "playing", "heat", "cold", "dry", "armed_home", "armed_away", "armed_vacation", "armed_custom_bypass", "triggered", "pending", "arming", "unlocked", 1] - "off": ["off", "closed", "closing", "false", "False", false, False, "standby", "paused", "idle", "disarmed", "disarming", "locked"] + "on": + - "on" + - "open" + - "opening" + - "true" + - "True" + - true + - True + - "playing" + - "heat" + - "cold" + - "dry" + - "armed_home" + - "armed_away" + - "armed_vacation" + - "armed_custom_bypass" + - "triggered" + - "pending" + - "arming" + - "unlocked" + - 1 + "off": + - "off" + - "closed" + - "closing" + - "false" + - "False" + - false + - False + - "standby" + - "paused" + - "idle" + - "disarmed" + - "disarming" + - "locked" + - 0 unknown: ["unknown", "unavailable", None, none, ""] climate: "on": ["heat_cool", "heat", "heating", "cold", "cooling", "dry", "drying", "fan", "fan_only", "auto"] "off": ["off", "idle"] alarm_control_panel: - "on": ["armed_home", "armed_away", "armed_vacation", "armed_custom_bypass", "triggered", "pending", "arming"] + "on": + - "armed_home" + - "armed_away" + - "armed_vacation" + - "armed_custom_bypass" + - "triggered" + - "pending" + - "arming" "off": ["disarmed", "disarming"] lock: "on": ["unlocked"] @@ -8086,7 +8162,11 @@ actions: ( ( overlap.icon_color - if overlap is defined and overlap.icon_color is defined and overlap.icon_color is sequence and overlap.icon_color | count == 3 + if + overlap is defined and + overlap.icon_color is defined and + overlap.icon_color is sequence and + overlap.icon_color | count == 3 else nextion.color.on ) if ((not entity_state_is_off) and (not entity_state_is_unknown)) @@ -8100,13 +8180,26 @@ actions: {{ ( overlap.name - if overlap is defined and overlap.name is defined and overlap.name is string and overlap.name | length > 0 - else (entity_friendly_name if entity_friendly_name is string and entity_friendly_name | length > 0 else entity_id) + if + overlap is defined and + overlap.name is defined and + overlap.name is string and + overlap.name | length > 0 + else + ( + entity_friendly_name + if entity_friendly_name is string and entity_friendly_name | length > 0 + else entity_id + ) ) if entity_id_valid }} icon: > {% if entity_id_valid %} - {% set icon_domain = nextion.icon.domain[entity_domain] | default(all_icons.unknown) if entity_domain else all_icons.unknown %} + {% set icon_domain = + nextion.icon.domain[entity_domain] | default(all_icons.unknown) + if entity_domain + else all_icons.unknown + %} {% if overlap is defined and overlap.icon is defined and @@ -8114,18 +8207,36 @@ actions: overlap.icon | length > 2 and overlap.icon.split(":") | count == 2 and overlap.icon.split(":")[1] in all_icons %} - {{ all_icons[overlap.icon.split(":")[1]] | default(icon_domain) if overlap.icon.split(":") | count == 2 else overlap.icon }} + {{ + all_icons[overlap.icon.split(":")[1]] | default(icon_domain) + if overlap.icon.split(":") | count == 2 + else overlap.icon + }} {% elif entity_domain == "climate" %} {% set entity_hvac_action = state_attr(entity_id, "hvac_action") | default("") %} - {% set entity_climate_action = (entity_hvac_action if entity_hvac_action and entity_hvac_action not in enum.states.unknown else entity_state) %} - {% if "off" in entity_climate_action %}{{ all_icons.thermostat }} - {% elif "heat_cool" in entity_climate_action %}{{ all_icons.autorenew }} - {% elif "heating" in entity_climate_action or "heat" in entity_climate_action %}{{ all_icons["thermometer-lines"] }} - {% elif "cooling" in entity_climate_action or "cool" in entity_climate_action %}{{ all_icons.snowflake }} - {% elif "drying" in entity_climate_action or "dry" in entity_climate_action %}{{ all_icons["water-percent"] }} - {% elif "fan" in entity_climate_action or "fan_only" in entity_climate_action %}{{ all_icons.fan }} - {% elif "auto" in entity_climate_action %}{{ all_icons["refresh-auto"] }} - {% elif "idle" in entity_climate_action %}{{ all_icons.thermometer }} + {% set entity_climate_action = + ( + entity_hvac_action + if entity_hvac_action and entity_hvac_action not in enum.states.unknown + else entity_state + ) + %} + {% if "off" in entity_climate_action %} + {{ all_icons.thermostat }} + {% elif "heat_cool" in entity_climate_action %} + {{ all_icons.autorenew }} + {% elif "heating" in entity_climate_action or "heat" in entity_climate_action %} + {{ all_icons["thermometer-lines"] }} + {% elif "cooling" in entity_climate_action or "cool" in entity_climate_action %} + {{ all_icons.snowflake }} + {% elif "drying" in entity_climate_action or "dry" in entity_climate_action %} + {{ all_icons["water-percent"] }} + {% elif "fan" in entity_climate_action or "fan_only" in entity_climate_action %} + {{ all_icons.fan }} + {% elif "auto" in entity_climate_action %} + {{ all_icons["refresh-auto"] }} + {% elif "idle" in entity_climate_action %} + {{ all_icons.thermometer }} {% else %}{{ icon_domain }} {% endif %} {% elif entity_domain == "alarm_control_panel" %} @@ -8153,9 +8264,23 @@ actions: {{ all_icons[entity_icon.split(":")[1]] }} {% elif entity_domain in ["binary_sensor", "cover", "sensor", "switch"] and - entity_device_class is defined and entity_device_class is string and entity_device_class | length > 0 %} - {% set entity_device_class_icon = entity_device_class + (("-" + entity_state) if entity_domain not in ["sensor"] else "") %} - {% set entity_device_class_icon = device_class_icons[entity_domain][entity_device_class_icon] if entity_device_class_icon in device_class_icons[entity_domain] else icon_domain %} + entity_device_class is defined and + entity_device_class is string and + entity_device_class | length > 0 + %} + {% set entity_device_class_icon = + entity_device_class + + ( + ("-" + entity_state) + if entity_domain not in ["sensor"] + else "" + ) + %} + {% set entity_device_class_icon = + device_class_icons[entity_domain][entity_device_class_icon] + if entity_device_class_icon in device_class_icons[entity_domain] + else icon_domain + %} {{ all_icons[entity_device_class_icon] if entity_device_class_icon in all_icons else icon_domain }} {% else %} {{ icon_domain }} @@ -8164,32 +8289,62 @@ actions: icon_color: > {% if entity_id_valid %} {% if entity_domain == "alarm_control_panel" %} - {% if entity_state == "disarmed" %}{{ nextion.color.off }} - {% elif entity_state in ["armed_home", "armed_away", "armed_night", "armed_vacation", "armed_bypass"] %}{{ nextion.color.green }} - {% elif entity_state in ["pending", "arming", "disarming"] %}{{ nextion.color.amber }} - {% elif entity_state == "triggered" %}{{ nextion.color.red }} - {% else %}{{ entity_icon_color }} + {% if entity_state == "disarmed" %} + {{ nextion.color.off }} + {% elif entity_state in ["armed_home", "armed_away", "armed_night", + "armed_vacation", "armed_bypass"] + %} + {{ nextion.color.green }} + {% elif entity_state in ["pending", "arming", "disarming"] %} + {{ nextion.color.amber }} + {% elif entity_state == "triggered" %} + {{ nextion.color.red }} + {% else %} + {{ entity_icon_color }} {% endif %} {% elif entity_domain == "climate" %} {% set entity_hvac_action = state_attr(entity_id, "hvac_action") | default("") %} - {% set entity_climate_action = (entity_hvac_action if entity_hvac_action and entity_hvac_action not in enum.states.unknown else entity_state) %} - {% if "off" in entity_climate_action %}{{ nextion.color.off }} - {% elif "heat_cool" in entity_climate_action %}{{ nextion.color.amber }} - {% elif "heating" in entity_climate_action or "heat" in entity_climate_action %}{{ nextion.color.deep_orange}} - {% elif "cooling" in entity_climate_action or "cool" in entity_climate_action %}{{ nextion.color.blue }} - {% elif "drying" in entity_climate_action or "dry" in entity_climate_action %}{{ nextion.color.orange }} - {% elif "fan" in entity_climate_action or "fan_only" in entity_climate_action %}{{ nextion.color.cyan }} - {% elif "auto" in entity_climate_action %}{{ nextion.color.green }} - {% elif "idle" in entity_climate_action %}{{ nextion.color.off }} - {% else %}{{ entity_icon_color }} + {% set entity_climate_action = + ( + entity_hvac_action + if entity_hvac_action and entity_hvac_action not in enum.states.unknown + else entity_state + ) + %} + {% if "off" in entity_climate_action %} + {{ nextion.color.off }} + {% elif "heat_cool" in entity_climate_action %} + {{ nextion.color.amber }} + {% elif "heating" in entity_climate_action or "heat" in entity_climate_action %} + {{ nextion.color.deep_orange}} + {% elif "cooling" in entity_climate_action or "cool" in entity_climate_action %} + {{ nextion.color.blue }} + {% elif "drying" in entity_climate_action or "dry" in entity_climate_action %} + {{ nextion.color.orange }} + {% elif "fan" in entity_climate_action or "fan_only" in entity_climate_action %} + {{ nextion.color.cyan }} + {% elif "auto" in entity_climate_action %} + {{ nextion.color.green }} + {% elif "idle" in entity_climate_action %} + {{ nextion.color.off }} + {% else %} + {{ entity_icon_color }} {% endif %} {% elif entity_domain == "light" %} {% if entity_state != "on" %}{{ nextion.color.off }} {% else %} {% set entity_rgb_color_attr = state_attr(entity_id, "rgb_color") | default("") %} - {% set entity_rgb_color = entity_rgb_color_attr if entity_rgb_color_attr is sequence and entity_rgb_color_attr | count == 3 else entity_icon_color %} + {% set entity_rgb_color = + entity_rgb_color_attr + if entity_rgb_color_attr is sequence and entity_rgb_color_attr | count == 3 + else entity_icon_color + %} {% set entity_brightness = state_attr(entity_id, "brightness") | default("") %} - {% set entity_brightness_index = (entity_brightness | int(255))/255 if is_number(entity_brightness) else 1 %} + {% set entity_brightness_index = + (entity_brightness | int(255))/255 + if is_number(entity_brightness) + else 1 + %} {{ [ min(200,entity_rgb_color[0] * entity_brightness_index) | round(0), @@ -8403,19 +8558,37 @@ actions: buttons: left: entity: '{{ hw_button_left_entity }}' - entity_is_valid: '{{ hw_button_left_entity is defined and hw_button_left_entity is string and hw_button_left_entity.split(".") | count == 2 }}' + entity_is_valid: > + {{ + hw_button_left_entity is defined and + hw_button_left_entity is string and + hw_button_left_entity.split(".") | count == 2 + }} state_entity: '{{ hw_button_left_state_entity }}' state_entity_is_valid: > - {{ hw_button_left_state_entity is defined and hw_button_left_state_entity is string and hw_button_left_state_entity.split(".") | count == 2 }} + {{ + hw_button_left_state_entity is defined and + hw_button_left_state_entity is string and + hw_button_left_state_entity.split(".") | count == 2 + }} name: !input 'left_button_name' hold_select: !input 'left_button_hold_select' bar_always_visible: !input hw_button_bar_left_always_show right: entity: '{{ hw_button_right_entity }}' - entity_is_valid: '{{ hw_button_right_entity is defined and hw_button_right_entity is string and hw_button_right_entity.split(".") | count == 2 }}' + entity_is_valid: > + {{ + hw_button_right_entity is defined and + hw_button_right_entity is string and + hw_button_right_entity.split(".") | count == 2 + }} state_entity: '{{ hw_button_right_state_entity }}' state_entity_is_valid: > - {{ hw_button_right_state_entity is defined and hw_button_right_state_entity is string and hw_button_right_state_entity.split(".") | count == 2 }} + {{ + hw_button_right_state_entity is defined and + hw_button_right_state_entity is string and + hw_button_right_state_entity.split(".") | count == 2 + }} name: !input 'right_button_name' hold_select: !input 'right_button_hold_select' bar_always_visible: !input hw_button_bar_right_always_show @@ -8466,7 +8639,11 @@ actions: hw_buttons_bar_color_on: !input hw_buttons_bar_color_on hw_buttons_bar_color_on_rgb565: > {{ - int(((hw_buttons_bar_color_on[0] //(2**3)) *(2**11))+((hw_buttons_bar_color_on[1] //(2**2)) *(2**5))+(hw_buttons_bar_color_on[2] //(2**3))) + int( + ((hw_buttons_bar_color_on[0] //(2**3))*(2**11))+ + ((hw_buttons_bar_color_on[1] //(2**2)) *(2**5))+ + (hw_buttons_bar_color_on[2] //(2**3)) + ) if hw_buttons_bar_color_on is sequence and hw_buttons_bar_color_on | count == 3 else 0 @@ -8474,7 +8651,11 @@ actions: hw_buttons_bar_color_off: !input hw_buttons_bar_color_off hw_buttons_bar_color_off_rgb565: > {{ - int(((hw_buttons_bar_color_off[0] //(2**3)) *(2**11))+((hw_buttons_bar_color_off[1] //(2**2)) *(2**5))+(hw_buttons_bar_color_off[2] //(2**3))) + int( + ((hw_buttons_bar_color_off[0] //(2**3)) *(2**11))+ + ((hw_buttons_bar_color_off[1] //(2**2)) *(2**5))+ + (hw_buttons_bar_color_off[2] //(2**3)) + ) if hw_buttons_bar_color_off is sequence and hw_buttons_bar_color_off | count == 3 else 0 @@ -8518,10 +8699,18 @@ actions: hardware.buttons.left.entity_is_valid }} hw_btn_left_state: > - {{ (states(hardware.buttons.left.state_entity) | default("unavailable") - if hardware.buttons.left.state_entity_is_valid - else (states(hardware.buttons.left.entity) | default("unavailable") - if hardware.buttons.left.entity_is_valid else "unavailable")) in enum.states.on }} + {{ + ( + states(hardware.buttons.left.state_entity) | default("unavailable") + if hardware.buttons.left.state_entity_is_valid + else + ( + states(hardware.buttons.left.entity) | default("unavailable") + if hardware.buttons.left.entity_is_valid + else "unavailable" + ) + ) in enum.states.on + }} hw_btn_left_flags: > {% if hw_btn_left_enabled is defined and hw_btn_left_enabled == False %} 3 @@ -8541,10 +8730,18 @@ actions: hardware.buttons.right.entity_is_valid }} hw_btn_right_state: > - {{ (states(hardware.buttons.right.state_entity) | default("unavailable") - if hardware.buttons.right.state_entity_is_valid - else (states(hardware.buttons.right.entity) | default("unavailable") - if hardware.buttons.right.entity_is_valid else "unavailable")) in enum.states.on }} + {{ + ( + states(hardware.buttons.right.state_entity) | default("unavailable") + if hardware.buttons.right.state_entity_is_valid + else + ( + states(hardware.buttons.right.entity) | default("unavailable") + if hardware.buttons.right.entity_is_valid + else "unavailable" + ) + ) in enum.states.on + }} hw_btn_right_flags: > {% if hw_btn_right_enabled is defined and hw_btn_right_enabled == False %} 3 @@ -8557,7 +8754,8 @@ actions: {% else %} 0 {% endif %} - hw_btn_combined_flags: '{{ (hw_btn_left_flags | int(0)) + ((hw_btn_right_flags | int(0)) * 4) }}' + hw_btn_combined_flags: > + {{ (hw_btn_left_flags | int(0)) + ((hw_btn_right_flags | int(0)) * 4) }} - *delay_default - alias: hw_button_state action: 'esphome.{{ nspanel_name }}_set_number' @@ -8729,7 +8927,12 @@ actions: sequence: - &variables_page_buttons variables: - event_page: '{{ nspanel_event.page if nspanel_event is defined and nspanel_event.page is defined else pages.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: > @@ -8760,35 +8963,83 @@ actions: | list }} sequence: &display_button_page_button - - condition: '{{ repeat.item.entity is defined and repeat.item.entity is string and repeat.item.entity | length > 0 }}' + - condition: > + {{ + repeat.item.entity is defined and + repeat.item.entity is string and + repeat.item.entity | length > 0 + }} - variables: entity_id: '{{ repeat.item.entity }}' overlap: - icon: '{{ repeat.item.icon if repeat.item.icon is defined and repeat.item.icon is string and repeat.item.icon.split("mdi:")[1] in all_icons else None }}' - icon_color: '{{ repeat.item.icon_color_rgb if repeat.item.icon_color_rgb is defined else None }}' + icon: > + {{ + repeat.item.icon + if + repeat.item.icon is defined and + repeat.item.icon is string and + repeat.item.icon.split("mdi:")[1] in all_icons + else None + }} + icon_color: > + {{ + repeat.item.icon_color_rgb + if repeat.item.icon_color_rgb is defined + else None + }} name: '{{ repeat.item.name if repeat.item.name is defined else None }}' - *variable_entity - variables: current_entity_state_available: '{{ entity_state not in ["unavailable"] }}' btn_state: > # Button state (on = true or off = false) {{ - (entity_state in enum.states.on and entity_domain not in ["automation"]) - or (entity_domain == "climate" and entity_state != "off") - or (entity_domain in ["button", "input_button", "scene", "automation", "remote"] and trigger.id is match "current_state_entity") + (entity_state in enum.states.on and entity_domain not in ["automation"]) or + (entity_domain == "climate" and entity_state != "off") or + ( + entity_domain in ["button", "input_button", + "scene", "automation", "remote"] and + trigger.id is match "current_state_entity" + ) }} btn_bri_txt: > # Buttons value (brightness, temperature, etc.) {% if not has_value(entity_id) %} 0 {% elif entity_domain == "light" and entity_state == "on" %} {% set entity_brightness = state_attr(entity_id, "brightness") %} - {% set entity_brightness_index = entity_brightness/255 if entity_brightness and is_number(entity_brightness) else 0 %} + {% set entity_brightness_index = + entity_brightness/255 + if entity_brightness and is_number(entity_brightness) + else 0 + %} {{ (entity_brightness_index*100) | round(0) }}% - {% elif entity_domain == "fan" and entity_state == "on" and state_attr(entity_id, "percentage") | int(0) > 0 %} + {% elif + entity_domain == "fan" and + entity_state == "on" and + state_attr(entity_id, "percentage") | int(0) > 0 + %} {{ state_attr(entity_id, "percentage") | round(0, default=0) }}% - {% elif entity_domain == "cover" and entity_state in ["open", "opening", "closing"] and is_number(state_attr(entity_id, "current_position")) %} + {% elif + entity_domain == "cover" and + entity_state in ["open", "opening", "closing"] and + is_number(state_attr(entity_id, "current_position")) + %} {{ (state_attr(entity_id, "current_position") | int(100)) | round(0) }}% - {% elif entity_domain == "climate" and is_number(state_attr(entity_id, 'current_temperature')) %} - {% set current_temperature = state_attr(entity_id, 'current_temperature') | float %} - {{ current_temperature | round(0 if current_temperature >= 100 or temperature_units in ["F", "f", "°F", "°f", "K", "k"] else 1) }}{{ temperature_units}} + {% elif + entity_domain == "climate" and + is_number(state_attr(entity_id, 'current_temperature')) + %} + {% set current_temperature = + state_attr(entity_id, 'current_temperature') | float + %} + {{ + current_temperature + | round( + 0 + if + current_temperature >= 100 or + temperature_units in ["F", "f", "°F", "°f", "K", "k"] + else 1 + ) + }}{{ temperature_units}} {% else %} 0 {% endif %} - *delay_default @@ -8801,13 +9052,20 @@ actions: state: '{{ btn_state if btn_state else false }}' icon: '{{ entity.icon }}' icon_color: '{{ entity.icon_color }}' - icon_font: '{{ button_pages_icon_size if is_number(button_pages_icon_size) else 8 }}' + icon_font: > + {{ + button_pages_icon_size + if is_number(button_pages_icon_size) + else 8 + }} bri: '{{ btn_bri_txt if btn_bri_txt and btn_bri_txt != "0%" else "" }}' label: '{{ entity.name }}' continue_on_error: true - - if: - - '{{ entity_domain in ["automation", "button", "input_button", "remote", "scene"] }}' - - '{{ trigger.id is match "current_state_entity" }}' + - if: > + {{ + entity_domain in ["automation", "button", "input_button", "remote", "scene"] + and trigger.id is match "current_state_entity" + }} then: - delay: milliseconds: 800 @@ -8820,7 +9078,12 @@ actions: state: false icon: '{{ entity.icon }}' icon_color: '{{ nextion.color.grey_light }}' - icon_font: '{{ button_pages_icon_size if is_number(button_pages_icon_size) else 8 }}' + icon_font: > + {{ + button_pages_icon_size + if is_number(button_pages_icon_size) + else 8 + }} bri: '{{ btn_bri_txt }}' label: '{{ entity.name }}' continue_on_error: true @@ -8967,7 +9230,12 @@ actions: action: 'esphome.{{ nspanel_name }}_set_number' data: component: page_entity_value_horizontal_alignment - val: '{{ int(entitypages_value_alignment) if is_number(entitypages_value_alignment) else 0 }}' + val: > + {{ + int(entitypages_value_alignment) + if is_number(entitypages_value_alignment) + else 0 + }} continue_on_error: true - alias: BOOT_STEP_PAGE_FAN @@ -9028,7 +9296,7 @@ actions: }} font: -1 color: !input home_indoor_temp_icon_color - visible: '{{ home_indoor_temp_visible }}' + visible: !input home_indoor_temp_visible continue_on_error: true - alias: Home page outdoor temperature @@ -9094,15 +9362,22 @@ actions: - if: '{{ entity_has_value }}' then: - variables: - unit_of_measurement_raw: '{{ state_attr(entity_id, "unit_of_measurement") | default("") }}' + unit_of_measurement_raw: > + {{ state_attr(entity_id, "unit_of_measurement") | default("") }} unit_of_measurement: > {{ unit_of_measurement_raw - if unit_of_measurement_raw and unit_of_measurement_raw is string and unit_of_measurement_raw | length > 0 + if + unit_of_measurement_raw and + unit_of_measurement_raw is string and + unit_of_measurement_raw | length > 0 else "" }} - alias: Value's icon - if: '{{ is_boot or (overlap.icon is not string) }}' # Do not plot icon if it has overlap + if: + - or: + - '{{ is_boot }}' + - '{{ (overlap.icon is not string) }}' # Do not plot if it has overlap then: - *delay_default - alias: Send value's icon @@ -9134,7 +9409,15 @@ actions: txt: &value_with_unit_and_translations > {{ ( - (states(entity_id, rounded=true) ~ (unit_of_measurement if unit_of_measurement is string and unit_of_measurement | length > 0 else "")) + ( + states(entity_id, rounded=true) ~ ( + unit_of_measurement + if + unit_of_measurement is string and + unit_of_measurement | length > 0 + else "" + ) + ) if is_number(entity_state) else state_translated(entity_id) ) @@ -9201,7 +9484,11 @@ actions: }} entity_state: > {{ - (entity_hvac_action if entity_hvac_action and entity_hvac_action not in enum.states.unknown else entity_state) + ( + entity_hvac_action + if entity_hvac_action and entity_hvac_action not in enum.states.unknown + else entity_state + ) if entity_domain == "climate" else entity_state }} @@ -9211,16 +9498,29 @@ actions: (not repeat.item.inverted) and ( (entity_state in enum.states.on) or - (entity_domain != "climate" and entity_domain in enum.states and entity_state in enum.states[entity_domain].on) or - (entity_domain == "climate" and entity_state in ["heating", "cooling", "drying", "fan_only"]) + ( + entity_domain != "climate" and + entity_domain in enum.states and + entity_state in enum.states[entity_domain].on + ) or + ( + entity_domain == "climate" and + entity_state in ["heating", "cooling", "drying", "fan_only"] + ) ) ) or ( (repeat.item.inverted) and ( (entity_state in enum.states.off) or - (entity_domain in enum.states and entity_state in enum.states[entity_domain].off) or - (entity_domain == "climate" and entity_state not in ["heating", "cooling", "drying", "fan_only"]) + ( + entity_domain in enum.states and + entity_state in enum.states[entity_domain].off + ) or + ( + entity_domain == "climate" and + entity_state not in ["heating", "cooling", "drying", "fan_only"] + ) ) ) }} @@ -9269,7 +9569,15 @@ actions: - variables: entity_id: '{{ repeat.item.entity }}' overlap: - icon: '{{ repeat.item.icon if repeat.item.icon is defined and repeat.item.icon is string and repeat.item.icon.split("mdi:")[1] in all_icons else None }}' + icon: > + {{ + repeat.item.icon + if + repeat.item.icon is defined and + repeat.item.icon is string and + repeat.item.icon.split("mdi:")[1] in all_icons + else None + }} - *variable_entity - action: 'esphome.{{ nspanel_name }}_icon' data: @@ -9481,7 +9789,9 @@ actions: icon: > {{ all_icons[bt_utilities_icon.split("mdi:")[1]] - if bt_utilities_icon is string and bt_utilities_icon.split("mdi:")[1] in all_icons + if + bt_utilities_icon is string and + bt_utilities_icon.split("mdi:")[1] in all_icons else all_icons.gauge }} color: !input home_button08_icon_color @@ -9501,7 +9811,11 @@ actions: data: component: "weather_pic" val: > - {% set weather_state = states(weather_entity) | default("unavailable") if weather_entity is string and has_value(weather_entity) else "unavailable" %} + {% set weather_state = + states(weather_entity) | default("unavailable") + if weather_entity is string and has_value(weather_entity) + else "unavailable" + %} {{ nextion.pic.weather[weather_state] | default(1) if weather_state in nextion.pic.weather @@ -9530,15 +9844,26 @@ actions: - alias: NSPanel action call conditions: - '{{ nspanel_event.type == "action_call"}}' - - '{{ nspanel_event.action is defined and nspanel_event.action is string and nspanel_event.action | length > 0 }}' - - '{{ nspanel_event.action.split(".") | count == 2 }}' # prevents call to null action - - '{{ nspanel_event.action.split(".")[0] | length > 0 and nspanel_event.action.split(".")[0] not in ["null", None] }}' # prevents call to null action - - '{{ nspanel_event.action.split(".")[1] | length > 0 and nspanel_event.action.split(".")[1] not in ["null", None] }}' # prevents call to null action - - '{{ nspanel_event.action | length > (2+nspanel_event.action.index(".")) }}' # prevents call to null action - - '{{ nspanel_event.action is not match "alarm_control_panel." }}' # Prevent the use of this call for alarm control due to safety reasons - - '{{ nspanel_event.entity is defined and nspanel_event.entity is string and nspanel_event.entity | length > 0 }}' + - '{{ nspanel_event.action is defined }}' + - '{{ nspanel_event.action is string }}' + - '{{ nspanel_event.action | length > 0 }}' + - '{{ nspanel_event.action.split(".") | count == 2 }}' # prevents call to null action + - '{{ nspanel_event.action.split(".")[0] | length > 0 }}' # prevents call to null action + - '{{ nspanel_event.action.split(".")[0] not in ["null", None] }}' # prevents call to null action + - '{{ nspanel_event.action.split(".")[1] | length > 0 }}' # prevents call to null action + - '{{ nspanel_event.action.split(".")[1] not in ["null", None] }}' # prevents call to null action + - '{{ nspanel_event.action | length > (2+nspanel_event.action.index(".")) }}' # prevents null action + - '{{ nspanel_event.action is not match "alarm_control_panel." }}' # Prevents use for alarm control + - '{{ nspanel_event.entity is defined }}' + - '{{ nspanel_event.entity is string }}' + - '{{ nspanel_event.entity | length > 0 }}' sequence: - - if: '{{ nspanel_event.key is defined and nspanel_event.key is string and nspanel_event.key | length > 0 }}' + - if: > + {{ + nspanel_event.key is defined and + nspanel_event.key is string and + nspanel_event.key | length > 0 + }} then: - choose: - alias: "climate.set_temperature" @@ -9582,7 +9907,8 @@ actions: - delay: milliseconds: 100 - variables: - percentage_srv: "fan.set_percentage" # This is used to fool engines checking for calls to unknown actions + # This is used to fool engines checking for calls to unknown actions + percentage_srv: "fan.set_percentage" - action: '{{ percentage_srv }}' data: percentage: '{{ nspanel_event.value }}' @@ -9606,7 +9932,9 @@ actions: conditions: - '{{ nspanel_event.action == "light.turn_on" }}' - '{{ nspanel_event.key == "rgb_color" }}' - - '{{ nspanel_event.red is defined and nspanel_event.green is defined and nspanel_event.blue is defined }}' + - '{{ nspanel_event.red is defined }}' + - '{{ nspanel_event.green is defined }}' + - '{{ nspanel_event.blue is defined }}' sequence: - action: '{{ nspanel_event.action }}' data: @@ -9652,7 +9980,10 @@ actions: outdoor_temp_state: > {{ states(outdoor_temp_entity, rounded=true) | default("unavailable") - if outdoor_temp_entity is string and outdoor_temp_entity is match "sensor." and has_value(outdoor_temp_entity) + if + outdoor_temp_entity is string and + outdoor_temp_entity is match "sensor." and + has_value(outdoor_temp_entity) else "unavailable" }} outdoor_temp: > @@ -9694,10 +10025,16 @@ actions: nspaneltemp_uom: '{{ state_attr(nspaneltemp, "unit_of_measurement") }}' indoor_temp_units: > {{ - indoor_temp.sensor_uom if indoor_temp.sensor_uom is string and indoor_temp.sensor_uom | length > 0 + indoor_temp.sensor_uom + if + indoor_temp.sensor_uom is string and + indoor_temp.sensor_uom | length > 0 else ( - indoor_temp.nspaneltemp_uom if indoor_temp.nspaneltemp_uom is string and indoor_temp.nspaneltemp_uom | length > 0 + indoor_temp.nspaneltemp_uom + if + indoor_temp.nspaneltemp_uom is string and + indoor_temp.nspaneltemp_uom | length > 0 else temperature_units ) }} @@ -9707,7 +10044,12 @@ actions: data: page: home component: indr_temp - txt: '{{ indoor_temp.state | round(1) ~ indoor_temp_units if not embedded_indoor_temperature else "" }}' + txt: > + {{ + indoor_temp.state | round(1) ~ indoor_temp_units + if not embedded_indoor_temperature + else "" + }} continue_on_error: true ###### Notification button ###### @@ -9720,9 +10062,11 @@ actions: bt_notific_icon: !input home_button04_icon notification_text: 'sensor.{{ nspanel_name }}_notification_text' notification_unread: 'binary_sensor.{{ nspanel_name }}_notification_unread' - notification_text_state: '{{ states(notification_text) if has_value(notification_text) else "" }}' + notification_text_state: > + {{ states(notification_text) if has_value(notification_text) else "" }} notification_unread_state: '{{ states(notification_unread) | default(true) }}' - notification_visible: '{{ notification_text_state is string and notification_text_state | length > 0 }}' + notification_visible: > + {{ notification_text_state is string and notification_text_state | length > 0 }} notification_icon: > {{ ( @@ -9861,15 +10205,27 @@ actions: {{ nspanel_event.entity if nspanel_event is defined and nspanel_event.entity is defined - else (trigger.entity_id if trigger.entity_id is defined else trigger.event.data.entity_id) + else + ( + trigger.entity_id + if trigger.entity_id is defined + else trigger.event.data.entity_id + ) }} - &variables_light_modes variables: - entity_id_valid: '{{ entity_id is defined and entity_id is string and entity_id.split(".") | count == 2 }}' + entity_id_valid: > + {{ + entity_id is defined and + entity_id is string and + entity_id.split(".") | count == 2 + }} entity_domain: '{{ entity_id.split(".")[0] if entity_id_valid }}' supported_features: '{{ state_attr(entity_id, "supported_features") | int(0) }}' - supported_color_modes_temp: '{{ state_attr(entity_id, "supported_color_modes") | default([]) }}' - supported_color_modes: '{{ supported_color_modes_temp if supported_color_modes_temp else [] }}' + supported_color_modes_temp: > + {{ state_attr(entity_id, "supported_color_modes") | default([]) }} + supported_color_modes: > + {{ supported_color_modes_temp if supported_color_modes_temp else [] }} color_mode_brightness: > {{ entity_domain == "light" and @@ -9889,7 +10245,8 @@ actions: enum.ColorMode.XY in supported_color_modes or enum.ColorMode.RGB in supported_color_modes or enum.ColorMode.RGBW in supported_color_modes or - enum.ColorMode.RGBWW in supported_color_modes or "hs" in supported_color_modes or + enum.ColorMode.RGBWW in supported_color_modes or + "hs" in supported_color_modes or "xy" in supported_color_modes or "rgb" in supported_color_modes or "rgbw" in supported_color_modes or @@ -9908,7 +10265,8 @@ actions: ) }} - variables: - curr_brightness: '{{ (state_attr(entity_id, "brightness") | int(0) * 100 / 255) | round(0) }}' + curr_brightness: > + {{ (state_attr(entity_id, "brightness") | int(0) * 100 / 255) | round(0) }} - *delay_default - alias: Light slider val action: 'esphome.{{ nspanel_name }}_component_val' @@ -10035,7 +10393,12 @@ actions: {{ nspanel_event.entity if nspanel_event is defined and nspanel_event.entity is defined - else (trigger.entity_id if trigger.entity_id is defined else trigger.event.data.entity_id) + else + ( + trigger.entity_id + if trigger.entity_id is defined + else trigger.event.data.entity_id + ) }} entity_device_class: '{{ state_attr(cover_entity, "device_class") | default("") }}' cover_icons: @@ -10117,9 +10480,17 @@ actions: | round(0) }} {% elif has_value(cover_entity | replace("cover.","sensor.") ~ "_battery") %} - {{ states(cover_entity | replace("cover.","sensor.") ~ "_battery", rounded=true) | default("unavailable") }} - {% elif has_value(cover_entity | replace("cover.","sensor.") | replace("cover", "battery")) %} - {{ states(cover_entity | replace("cover.","sensor.") | replace("cover", "battery"), rounded=true) | default("unavailable") }} + {{ + states(cover_entity | replace("cover.","sensor.") ~ "_battery", rounded=true) + | default("unavailable") + }} + {% elif + has_value(cover_entity | replace("cover.","sensor.") | replace("cover", "battery")) + %} + {{ + states(cover_entity | replace("cover.","sensor.") | replace("cover", "battery"), + rounded=true) | default("unavailable") + }} {% else %} unavailable {% endif %} - alias: Cover battery show @@ -10168,7 +10539,12 @@ actions: {{ nspanel_event.entity if nspanel_event is defined and nspanel_event.entity is defined - else (trigger.entity_id if trigger.entity_id is defined else trigger.event.data.entity_id) + else + ( + trigger.entity_id + if trigger.entity_id is defined + else trigger.event.data.entity_id + ) }} fan: supported_features: '{{ state_attr(fan_entity, "supported_features") | int(0) }}' @@ -10192,7 +10568,12 @@ actions: data: page: fan component: bt_oscillate - txt: '{{ all_icons["autorenew"] if state_attr(fan_entity, "oscillating") | default(false) else all_icons["autorenew-off"] }}' + txt: > + {{ + all_icons["autorenew"] + if state_attr(fan_entity, "oscillating") | default(false) + else all_icons["autorenew-off"] + }} continue_on_error: true - *delay_default - action: 'esphome.{{ nspanel_name }}_component_color' @@ -10208,7 +10589,9 @@ actions: component: bt_oscillate show: true continue_on_error: true - - condition: '{{ fan.steps > 0 and fan.supported_features | bitwise_and(1) > 0 }}' # Set speed + - condition: + - '{{ fan.steps > 0 }}' + - '{{ fan.supported_features | bitwise_and(1) > 0 }}' # Set speed - *delay_default - action: 'esphome.{{ nspanel_name }}_component_val' data: @@ -10233,14 +10616,24 @@ actions: data: page: fan component: button_up - color: '{{ nextion.color.grey_white if fan.percentage < 100 else nextion.color.grey_dark }}' + color: > + {{ + nextion.color.grey_white + if fan.percentage < 100 + else nextion.color.grey_dark + }} continue_on_error: true - *delay_default - action: 'esphome.{{ nspanel_name }}_component_color' data: page: fan component: button_down - color: '{{ nextion.color.grey_white if fan.percentage > 0 else nextion.color.grey_dark }}' + color: > + {{ + nextion.color.grey_white + if fan.percentage > 0 + else nextion.color.grey_dark + }} continue_on_error: true - *delay_default - action: 'esphome.{{ nspanel_name }}_component_color' @@ -10259,7 +10652,12 @@ actions: {{ nspanel_event.entity if nspanel_event is defined and nspanel_event.entity is defined - else (trigger.entity_id if trigger.entity_id is defined else trigger.event.data.entity_id) + else + ( + trigger.entity_id + if trigger.entity_id is defined + else trigger.event.data.entity_id + ) }} wait_completed: false - alias: Refresh page in a loop @@ -10274,18 +10672,38 @@ actions: - variables: media_player: state: '{{ states(media_player_entity) }}' - is_volume_muted: '{{ state_attr(media_player_entity, "is_volume_muted") | default(false) }}' - friendly_name: '{{ state_attr(media_player_entity, "friendly_name") | default("Media player") }}' - volume_level: '{{ (state_attr(media_player_entity, "volume_level") | round(2, default=0) * 100) | int(0) }}' + is_volume_muted: > + {{ + state_attr(media_player_entity, "is_volume_muted") + | default(false) + }} + friendly_name: > + {{ + state_attr(media_player_entity, "friendly_name") + | default("Media player") + }} + volume_level: > + {{ + (state_attr(media_player_entity, "volume_level") | round(2, default=0) * 100) + | int(0) + }} media_title: '{{ state_attr(media_player_entity, "media_title") }}' media_artist: '{{ state_attr(media_player_entity, "media_artist") }}' media_duration: '{{ state_attr(media_player_entity, "media_duration") | int(0) }}' media_position: '{{ state_attr(media_player_entity, "media_position") | int(0) }}' - media_position_updated_at: '{{ state_attr(media_player_entity, "media_position_updated_at") | default(now()) }}' + media_position_updated_at: > + {{ + state_attr(media_player_entity, "media_position_updated_at") + | default(now()) + }} supported_features: > {{ (1+4+8+16+32+128+256+512+4096+16384) - if (state_attr(media_player_entity, "mass_player_type") | default("")) == "group" + if + ( + state_attr(media_player_entity, "mass_player_type") + | default("") + ) == "group" else state_attr(media_player_entity, "supported_features") | int(0) }} - *delay_default @@ -10293,8 +10711,18 @@ actions: data: entity: '{{ media_player_entity }}' state: '{{ media_player.state if media_player.state is string else "" }}' - is_volume_muted: '{{ media_player.is_volume_muted if media_player.is_volume_muted is boolean else false }}' - friendly_name: '{{ media_player.friendly_name if media_player.friendly_name is string else "" }}' + is_volume_muted: > + {{ + media_player.is_volume_muted + if media_player.is_volume_muted is boolean + else false + }} + friendly_name: > + {{ + media_player.friendly_name + if media_player.friendly_name is string + else "" + }} volume_level: '{{ media_player.volume_level }}' media_title: > {{ @@ -10320,10 +10748,15 @@ actions: media_position: '{{ media_player.media_position }}' media_position_delta: > {{ - (now() | as_timestamp - media_player.media_position_updated_at | as_timestamp | default(now() | as_timestamp)) + ( + now() | as_timestamp - + media_player.media_position_updated_at + | as_timestamp | + default(now() | as_timestamp)) if media_player.media_position_updated_at and - media_player.media_position_updated_at not in [None, none, "", "unknown", "unavailable", false, 0] + media_player.media_position_updated_at not in [None, none, "", "unknown", + "unavailable", false, 0] else 0 }} supported_features: '{{ media_player.supported_features }}' @@ -10337,7 +10770,8 @@ actions: until: - or: - '{{ wait_completed }}' - - '{{ states(currentpage) != pages.media_player }}' # Don't replace this by pages.current as this have to be evaluated all the time + # Don't replace this by pages.current as this have to be evaluated all the time + - '{{ states(currentpage) != pages.media_player }}' - '{{ nspanel_event.type != "page_changed" }}' ## PAGE ALARM ## @@ -10349,7 +10783,12 @@ actions: {{ nspanel_event.entity if nspanel_event is defined and nspanel_event.entity is defined - else (trigger.entity_id if trigger.entity_id is defined else trigger.event.data.entity_id) + else + ( + trigger.entity_id + if trigger.entity_id is defined + else trigger.event.data.entity_id + ) }} alarm_entity: > {{ @@ -10364,10 +10803,12 @@ actions: supported_features: '{{ state_attr(entity_id, "supported_features") | default(0) }}' - *variable_entity - condition: '{{ supported_features > 0 }}' - - variables: # https://github.com/home-assistant/core/blob/dev/homeassistant/components/alarm_control_panel/const.py + # https://github.com/home-assistant/core/blob/dev/homeassistant/components/alarm_control_panel/const.py + - variables: alarm: code_format: '{{ state_attr(entity_id, "code_format") }}' - code_arm_required: '{{ state_attr(entity_id, "code_arm_required") | default(true) }}' + code_arm_required: > + {{ state_attr(entity_id, "code_arm_required") | default(true) }} - *delay_default - action: 'esphome.{{ nspanel_name }}_page_alarm' data: @@ -10375,7 +10816,8 @@ actions: state: '{{ entity_state }}' supported_features: '{{ supported_features }}' code_format: '{{ alarm.code_format if alarm.code_format else "none" }}' - code_arm_required: '{{ alarm.code_arm_required if alarm.code_arm_required else false }}' + code_arm_required: > + {{ alarm.code_arm_required if alarm.code_arm_required else false }} entity: '{{ entity_id }}' mui_alarm: '{{ dict.values(mui[language].alarm) | list }}' continue_on_error: true @@ -10411,12 +10853,20 @@ actions: {{ nspanel_event.entity if nspanel_event is defined and nspanel_event.entity is defined - else (trigger.entity_id if trigger.entity_id is defined else trigger.event.data.entity_id) + else + ( + trigger.entity_id + if trigger.entity_id is defined + else trigger.event.data.entity_id + ) }} climate_entity: > {{ climate_entity_temp - if climate_entity_temp is string and climate_entity_temp | length > 0 and climate_entity_temp != "embedded_climate" + if + climate_entity_temp is string and + climate_entity_temp | length > 0 and + climate_entity_temp != "embedded_climate" else climate }} settings_entity_domain: > @@ -10428,7 +10878,8 @@ actions: climate_entity.split(".") | count > 0 else "unknown" }} - hvac_modes: '{{ state_attr(climate_entity, "hvac_modes") if settings_entity_domain == "climate" }}' + hvac_modes: > + {{ state_attr(climate_entity, "hvac_modes") if settings_entity_domain == "climate" }} - condition: '{{ settings_entity_domain == "climate" }}' - *delay_default - action: 'esphome.{{ nspanel_name }}_component_text' @@ -10510,42 +10961,93 @@ actions: if: '{{ not (climate_entity == climate and embedded_climate) }}' then: - variables: - current_temp: '{{ state_attr(climate_entity, "current_temperature") | float(-999) | round(1) }}' + current_temp: > + {{ state_attr(climate_entity, "current_temperature") | float(-999) | round(1) }} supported_features: '{{ state_attr(climate_entity, "supported_features") | int(0) }}' is_target_temperature: '{{ supported_features | bitwise_and(1) > 0 }}' is_target_temperature_range: '{{ supported_features | bitwise_and(2) > 0 }}' - target_temp: '{{ state_attr(climate_entity, "temperature") | float(-999) | round(1) if is_target_temperature else -999 }}' - target_temp_high: '{{ state_attr(climate_entity, "target_temp_high") | float(-999) | round(1) if is_target_temperature_range else -999 }}' - target_temp_low: '{{ state_attr(climate_entity, "target_temp_low") | float(-999) | round(1) if is_target_temperature_range else -999 }}' + target_temp: > + {{ + state_attr(climate_entity, "temperature") | float(-999) | round(1) + if is_target_temperature + else -999 + }} + target_temp_high: > + {{ + state_attr(climate_entity, "target_temp_high") | float(-999) | round(1) + if is_target_temperature_range + else -999 + }} + target_temp_low: > + {{ + state_attr(climate_entity, "target_temp_low") | float(-999) | round(1) + if is_target_temperature_range + else -999 + }} - variables: is_target_temperature: '{{ is_target_temperature and target_temp > -999 }}' - is_target_temperature_range: '{{ is_target_temperature_range and target_temp_high > -999 and target_temp_low > -999 }}' + is_target_temperature_range: > + {{ + is_target_temperature_range and + target_temp_high > -999 and + target_temp_low > -999 + }} temp_step: > {% set target_temp_step = state_attr(climate_entity, "target_temp_step") %} {% if not is_number(target_temp_step) %} {% set target_temp_step = state_attr(climate_entity, "target_temperature_step") %} {% endif %} {% set target_temp_step = target_temp_step | float(0.5) | abs %} - {{ ((10 * target_temp_step) | round(0) | int) if is_number(target_temp_step) and target_temp_step > 0 else 10 }} - temp_offset_raw: '{{ (state_attr(climate_entity, "min_temp") | float(7) * 10) | round(0) | int }}' - temp_offset: '{{ temp_offset_raw if (temp_offset_raw % temp_step) == 0 else temp_offset_raw + temp_step - (temp_offset_raw % temp_step) }}' - max_temp_raw: '{{ (state_attr(climate_entity, "max_temp") | float(35) * 10) | round(0) | int }}' + {{ + ((10 * target_temp_step) | round(0) | int) + if is_number(target_temp_step) and target_temp_step > 0 + else 10 + }} + temp_offset_raw: > + {{ (state_attr(climate_entity, "min_temp") | float(7) * 10) | round(0) | int }} + temp_offset: > + {{ + temp_offset_raw + if (temp_offset_raw % temp_step) == 0 + else temp_offset_raw + temp_step - (temp_offset_raw % temp_step) + }} + max_temp_raw: > + {{ (state_attr(climate_entity, "max_temp") | float(35) * 10) | round(0) | int }} max_temp: '{{ (max_temp_raw / temp_step) | round * temp_step }}' total_steps: '{{ ((max_temp-temp_offset)/temp_step) | round(0) | int }}' - climate_state: '{{ states(climate_entity) | default("unavailable") if climate_entity is string else "unavailable" }}' + climate_state: > + {{ + states(climate_entity) | default("unavailable") + if climate_entity is string + else "unavailable" + }} hvac_action: '{{ state_attr(climate_entity, "hvac_action") | default("") }}' hvac_modes: '{{ state_attr(climate_entity, "hvac_modes") }}' - climate_action: '{{ hvac_action if hvac_action and hvac_action not in enum.states.unknown else climate_state }}' + climate_action: > + {{ + hvac_action + if hvac_action and hvac_action not in enum.states.unknown + else climate_state + }} climate_icon: > - {% if "off" in climate_action %}{{ all_icons.blank }} - {% elif "heat_cool" in climate_action %}{{ all_icons.autorenew }} - {% elif "heating" in climate_action or "heat" in climate_action %}{{ all_icons["thermometer-lines"] }} - {% elif "cooling" in climate_action or "cool" in climate_action %}{{ all_icons.snowflake }} - {% elif "drying" in climate_action or "dry" in climate_action %}{{ all_icons["water-percent"] }} - {% elif "fan" in climate_action or "fan_only" in climate_action %}{{ all_icons.fan }} - {% elif "auto" in climate_action %}{{ all_icons["refresh-auto"] }} - {% elif "idle" in climate_action %}{{ all_icons.thermometer }} - {% else %}{{ all_icons.blank }} + {% if "off" in climate_action %} + {{ all_icons.blank }} + {% elif "heat_cool" in climate_action %} + {{ all_icons.autorenew }} + {% elif "heating" in climate_action or "heat" in climate_action %} + {{ all_icons["thermometer-lines"] }} + {% elif "cooling" in climate_action or "cool" in climate_action %} + {{ all_icons.snowflake }} + {% elif "drying" in climate_action or "dry" in climate_action %} + {{ all_icons["water-percent"] }} + {% elif "fan" in climate_action or "fan_only" in climate_action %} + {{ all_icons.fan }} + {% elif "auto" in climate_action %} + {{ all_icons["refresh-auto"] }} + {% elif "idle" in climate_action %} + {{ all_icons.thermometer }} + {% else %} + {{ all_icons.blank }} {% endif %} - *delay_default - action: 'esphome.{{ nspanel_name }}_page_climate' @@ -10560,7 +11062,12 @@ actions: temp_offset: '{{ temp_offset }}' climate_icon: '{{ climate_icon }}' embedded_climate: '{{ climate_entity == thermostat_embedded }}' - entity: '{{ "embedded_climate" if climate_entity == thermostat_embedded else climate_entity }}' + entity: > + {{ + "embedded_climate" + if climate_entity == thermostat_embedded + else climate_entity + }} continue_on_error: true ##### Climate buttons ##### @@ -10618,9 +11125,20 @@ actions: component: button09 - &climate-update_custom_buttons-update repeat: - for_each: '{{ climate_custom_buttons | selectattr("entity", "defined") | rejectattr("entity", "eq", []) | list }}' + for_each: > + {{ + climate_custom_buttons + | selectattr("entity", "defined") + | rejectattr("entity", "eq", []) + | list + }} sequence: - - condition: '{{ repeat.item.entity is defined and repeat.item.entity is string and repeat.item.entity | length > 0 }}' + - condition: > + {{ + repeat.item.entity is defined and + repeat.item.entity is string and + repeat.item.entity | length > 0 + }} - variables: entity_id: '{{ repeat.item.entity }}' overlap: @@ -10658,7 +11176,12 @@ actions: 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 pages.current }}' + event_page: > + {{ + nspanel_event.page + if nspanel_event is defined and nspanel_event.page is defined + else pages.current + }} entitypages_show_entities_icons: !input entitypages_show_entities_icons ##### Entity page - Label ##### - if: '{{ entities_pages.labels[event_page] | length > 0 }}' @@ -10687,9 +11210,18 @@ actions: - variables: entity_id: '{{ repeat.item.entity }}' overlap: - icon: '{{ repeat.item.icon if repeat.item.icon is defined and repeat.item.icon is string and repeat.item.icon.split("mdi:")[1] in all_icons else None }}' + icon: > + {{ + repeat.item.icon + if + repeat.item.icon is defined and + repeat.item.icon is string and + repeat.item.icon.split("mdi:")[1] in all_icons + else None + }} name: '{{ repeat.item.name if repeat.item.name is defined else None }}' - unit_of_measurement: '{{ state_attr(entity_id, "unit_of_measurement") | default("") }}' + unit_of_measurement: > + {{ state_attr(entity_id, "unit_of_measurement") | default("") }} - *variable_entity - *delay_default - action: 'esphome.{{ nspanel_name }}_value' @@ -10708,7 +11240,8 @@ actions: conditions: '{{ nspanel_event.page in pages.weatherpages }}' sequence: - variables: - weather_attribution: '{{ state_attr(weather_entity, "attribution") if weather_entity is string }}' + weather_attribution: > + {{ state_attr(weather_entity, "attribution") if weather_entity is string }} weather_type: > {% if not weather_attribution %} unavailable {% elif "AccuWeather" in weather_attribution %} AccuWeather @@ -10739,18 +11272,34 @@ actions: precipitation_probability: > {{ state_attr(weather_entity, "precipitation_probability_unit") | default("%") - if weather_entity is string and state_attr(weather_entity, "precipitation_probability_unit") + if + weather_entity is string and + state_attr(weather_entity, "precipitation_probability_unit") else "%" }} - pressure: '{{ state_attr(weather_entity, "pressure_unit") | default("") if weather_entity is string and state_attr(weather_entity, "pressure_unit") }}' + pressure: > + {{ + state_attr(weather_entity, "pressure_unit") | default("") + if weather_entity is string and state_attr(weather_entity, "pressure_unit") + }} thunderstorm_probability: > {{ state_attr(weather_entity, "thunderstorm_probability_unit") | default("%") - if weather_entity is string and state_attr(weather_entity, "thunderstorm_probability_unit") + if + weather_entity is string and + state_attr(weather_entity, "thunderstorm_probability_unit") else "%" }} - uv_index: '{{ state_attr(weather_entity, "uv_index_unit") | default("") if weather_entity is string and state_attr(weather_entity, "uv_index_unit") }}' - wind_speed: '{{ state_attr(weather_entity, "wind_speed_unit") | default("") if weather_entity is string and state_attr(weather_entity, "wind_speed_unit") }}' + uv_index: > + {{ + state_attr(weather_entity, "uv_index_unit") | default("") + if weather_entity is string and state_attr(weather_entity, "uv_index_unit") + }} + wind_speed: > + {{ + state_attr(weather_entity, "wind_speed_unit") | default("") + if weather_entity is string and state_attr(weather_entity, "wind_speed_unit") + }} wind_bearing: > {{ state_attr(weather_entity, "wind_bearing_unit") | default("°") @@ -10791,9 +11340,13 @@ actions: ##### Display weather data only when available ##### - variables: - weather_entity_supported_features: '{{ state_attr(weather_entity, "supported_features") | int(0) }}' + weather_entity_supported_features: > + {{ state_attr(weather_entity, "supported_features") | int(0) }} forecast_type: > - {% if weather_entity_supported_features == 0 or weather_entity_supported_features | bitwise_and(1) > 0 %} + {% if + weather_entity_supported_features == 0 or + weather_entity_supported_features | bitwise_and(1) > 0 + %} daily {% elif weather_entity_supported_features | bitwise_and(4) > 0 %} twice_daily @@ -10827,8 +11380,16 @@ actions: {{ forecast | default([]) | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | timestamp_utc ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | timestamp_utc ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | timestamp_utc + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | timestamp_utc + ) | list }} {% else %} @@ -10836,91 +11397,203 @@ actions: { 'datetime': '{{ forecast | default([]) | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | as_datetime ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | as_datetime ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | as_datetime + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | as_datetime + ) | map(attribute="datetime") | list | first | as_timestamp | timestamp_utc if forecast | default([]) | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | as_datetime ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | as_datetime ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | as_datetime + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | as_datetime + ) | map(attribute="datetime") | list | count > 0 else "" }}', 'condition': '{{ forecast | default([]) | selectattr("condition", "defined") | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | as_datetime ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | as_datetime ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | as_datetime + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | as_datetime + ) | map(attribute="condition") | list | first if forecast | default([]) | selectattr("condition", "defined") | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | as_datetime ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | as_datetime ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | as_datetime + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | as_datetime + ) | map(attribute="condition") | list | count > 0 else "" }}', 'temperature': '{{ forecast | default([]) | selectattr("temperature", "defined") | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | as_datetime ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | as_datetime ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | as_datetime + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | as_datetime + ) | map(attribute="temperature") | list | first if forecast | default([]) | selectattr("temperature", "defined") | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | as_datetime ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | as_datetime ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | as_datetime + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | as_datetime + ) | map(attribute="temperature") | list | count > 0 else "" }}', 'templow': '{{ forecast | default([]) | selectattr("templow", "defined") | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | as_datetime ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | as_datetime ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | as_datetime + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | as_datetime + ) | map(attribute="templow") | list | first if forecast | default([]) | selectattr("templow", "defined") | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | as_datetime ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | as_datetime ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | as_datetime + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | as_datetime + ) | map(attribute="templow") | list | count > 0 else "" }}', 'precipitation': '{{ forecast | default([]) | selectattr("precipitation", "defined") | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | as_datetime ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | as_datetime ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | as_datetime + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | as_datetime + ) | map(attribute="precipitation") | list | first if forecast | default([]) | selectattr("precipitation", "defined") | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | as_datetime ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | as_datetime ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | as_datetime + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | as_datetime + ) | map(attribute="precipitation") | list | count > 0 else "" }}', 'wind_speed': '{{ forecast | default([]) | selectattr("wind_speed", "defined") | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | as_datetime ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | as_datetime ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | as_datetime + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | as_datetime + ) | map(attribute="wind_speed") | list | first if forecast | default([]) | selectattr("wind_speed", "defined") | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | as_datetime ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | as_datetime ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | as_datetime + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | as_datetime + ) | map(attribute="wind_speed") | list | count > 0 else "" }}', 'wind_bearing': '{{ forecast | default([]) | selectattr("wind_bearing", "defined") | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | as_datetime ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | as_datetime ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | as_datetime + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | as_datetime + ) | map(attribute="wind_bearing") | list | first if forecast | default([]) | selectattr("wind_bearing", "defined") | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | as_datetime ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | as_datetime ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | as_datetime + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | as_datetime + ) | map(attribute="wind_bearing") | list | count > 0 else "" }}' } @@ -10930,14 +11603,26 @@ actions: then: # Display forecast - variables: metnoweather: '{{ weather_type == "Met.no" }}' - metnoweather_hourly_forecast: '{{ state_attr(weather_entity ~ "_hourly", "forecast") if metnoweather and has_value(weather_entity ~ "_hourly") }}' + metnoweather_hourly_forecast: > + {{ + state_attr(weather_entity ~ "_hourly", "forecast") + if metnoweather and has_value(weather_entity ~ "_hourly") + }} forecast_day: > {% if forecast_day | count > 0 %}{{ forecast_day }} {% elif metnoweather and metnoweather_hourly_forecast %} {{ metnoweather_hourly_forecast | selectattr("datetime", "defined") - | selectattr("datetime", ">=", (today_at("00:00") + timedelta(days= page_index)) | as_timestamp | timestamp_utc ) - | selectattr("datetime", "<", (today_at("00:00") + timedelta(days= (page_index+1))) | as_timestamp | timestamp_utc ) + | selectattr("datetime", ">=", + (today_at("00:00") + timedelta(days= page_index)) + | as_timestamp + | timestamp_utc + ) + | selectattr("datetime", "<", + (today_at("00:00") + timedelta(days= (page_index+1))) + | as_timestamp + | timestamp_utc + ) | list }} {% endif %} @@ -10959,12 +11644,24 @@ actions: - variables: accuweather: '{{ weather_type == "AccuWeather" }}' accuweather_day_name: '{{ "day_" ~ page_index }}' - accuweather_sensor_prefix: '{{ "sensor." ~ (weather_entity | replace("weather.","")) ~ "_" }}' + accuweather_sensor_prefix: > + {{ "sensor." ~ (weather_entity | replace("weather.","")) ~ "_" }} accuweather_sensor_sufix: '{{ "_" ~ page_index ~ "d" }}' temp_min: > {{ - forecast_day | selectattr("templow", "defined") | map(attribute="templow") | map("float") | list | min - if forecast_day | selectattr("templow", "defined") | map(attribute="templow") | map("float") | list | count > 0 + forecast_day + | selectattr("templow", "defined") + | map(attribute="templow") + | map("float") + | list + | min + if + forecast_day + | selectattr("templow", "defined") + | map(attribute="templow") + | map("float") + | list + | count > 0 else forecast_day | selectattr("temperature", "defined") @@ -11070,7 +11767,9 @@ actions: }} hours_of_sun: > {{ - states(accuweather_sensor_prefix ~ "hours_of_sun" ~ accuweather_sensor_sufix, rounded=true) | default("unknown") + states(accuweather_sensor_prefix ~ "hours_of_sun" ~ accuweather_sensor_sufix, + rounded=true) + | default("unknown") if accuweather else ( @@ -11094,7 +11793,9 @@ actions: }} uv_index: > {{ - states(accuweather_sensor_prefix ~ "uv_index" ~ accuweather_sensor_sufix, rounded=true) | default("unknown") + states(accuweather_sensor_prefix ~ "uv_index" ~ accuweather_sensor_sufix, + rounded=true) + | default("unknown") if accuweather else ( @@ -11118,7 +11819,13 @@ actions: }} thunderstorm_probability: > {{ - states(accuweather_sensor_prefix ~ "thunderstorm_probability_day" ~ accuweather_sensor_sufix, rounded=true) | default("unknown") + states( + accuweather_sensor_prefix ~ + "thunderstorm_probability_day" ~ + accuweather_sensor_sufix, + rounded=true + ) + | default("unknown") if accuweather else ( @@ -11161,23 +11868,52 @@ actions: parameters: - name: hours_of_sun visibility: '{{ is_number(hours_of_sun) }}' - value: '{{ (hours_of_sun ~ " " ~ weather_units.hours_of_sun) if is_number(hours_of_sun) }}' + value: > + {{ + (hours_of_sun ~ " " ~ weather_units.hours_of_sun) + if is_number(hours_of_sun) + }} icon: '{{ nextion.icon.weather.sun }}' - name: thunderstorm_probability visibility: '{{ is_number(thunderstorm_probability) }}' - value: '{{ (thunderstorm_probability ~ weather_units.thunderstorm_probability) if is_number(thunderstorm_probability) }}' + value: > + {{ + (thunderstorm_probability ~ weather_units.thunderstorm_probability) + if is_number(thunderstorm_probability) + }} icon: '{{ nextion.icon.weather.lightning }}' - name: precipitation - visibility: '{{ is_number(precipitation) or is_number(precipitation_probability) }}' + visibility: > + {{ is_number(precipitation) or is_number(precipitation_probability) }} value: > - {{ (precipitation ~ " " ~ weather_units.precipitation) if is_number(precipitation) }} - {{ "-" if is_number(precipitation) and is_number(precipitation_probability) }} - {{ (precipitation_probability ~ weather_units.precipitation_probability) if is_number(precipitation_probability) }} + {{ + (precipitation ~ " " ~ weather_units.precipitation) + if is_number(precipitation) + }} + {{ + "-" + if is_number(precipitation) and is_number(precipitation_probability) + }} + {{ + (precipitation_probability ~ weather_units.precipitation_probability) + if is_number(precipitation_probability) + }} icon: '{{ nextion.icon.weather.rain }}' - name: uv_index visibility: '{{ is_number(uv_index) }}' value: > - {{ (state_attr(accuweather_sensor_prefix ~ "uv_index" ~ accuweather_sensor_sufix, "level") | default("") ~ ": ") if weather_type == "AccuWeather" }} + {{ + ( + state_attr( + accuweather_sensor_prefix ~ + "uv_index" ~ + accuweather_sensor_sufix, + "level" + ) | default("") + ~ ": " + ) + if weather_type == "AccuWeather" + }} {{ (uv_index ~ weather_units.uv_index) if is_number(uv_index) }} icon: '{{ nextion.icon.weather.protect }}' - name: wind_speed @@ -11197,11 +11933,13 @@ actions: icon: '{{ nextion.icon.weather.wind }}' - name: humidity visibility: '{{ is_number(humidity) }}' - value: '{{ (humidity ~ " " ~ weather_units.humidity) if is_number(humidity) }}' + value: > + {{ (humidity ~ " " ~ weather_units.humidity) if is_number(humidity) }} icon: '{{ all_icons["water-percent"] }}' - name: pressure visibility: '{{ is_number(pressure) }}' - value: '{{ (pressure ~ " " ~ weather_units.pressure) if is_number(pressure) }}' + value: > + {{ (pressure ~ " " ~ weather_units.pressure) if is_number(pressure) }} icon: '{{ nextion.icon.weather.gauge }}' ##### Display weather PIC when available @@ -11212,7 +11950,12 @@ actions: data: cmd: > {{ page_name }}.weather_icon.pic={{ - nextion.pic.weather[states(weather_entity) | default("unavailable") if weather_entity is string else "unavailable"] | int(1) + nextion.pic.weather[ + states(weather_entity) + | default("unavailable") + if weather_entity is string + else "unavailable" + ] | int(1) if condition == "unknown" and page_name == pages.weatherpages[0] else nextion.pic.weather[condition] | int(1) }} @@ -11222,9 +11965,20 @@ actions: - variables: temperature_string: > {{ (temp_min | round(0) ~ temperature_units) if is_number(temp_min) }} - {{ "/" if is_number(temp_min) and is_number(temp_max) and temp_min != temp_max }} - {{ (temp_max | round(0) ~ temperature_units) if is_number(temp_max) and temp_min != temp_max }} - - if: '{{ (is_number(temp_min) or is_number(temp_max)) and temperature_string is string and temperature_string | length > 0 }}' + {{ + "/" + if is_number(temp_min) and is_number(temp_max) and temp_min != temp_max + }} + {{ + (temp_max | round(0) ~ temperature_units) + if is_number(temp_max) and temp_min != temp_max + }} + - if: > + {{ + (is_number(temp_min) or is_number(temp_max)) and + temperature_string is string and + temperature_string | length > 0 + }} then: - *delay_default - action: 'esphome.{{ nspanel_name }}_component_text' @@ -11269,7 +12023,13 @@ actions: ## Page title - variables: utilities_constructor_init: true - 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 }}' + 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 + }} - *delay_default - action: 'esphome.{{ nspanel_name }}_value' data: @@ -11286,8 +12046,15 @@ actions: for_each: '{{ pages_utilities.groups | list }}' sequence: &refresh_page_utilities_group - variables: - utilities_constructor: '{{ utilities_constructor_init is defined and utilities_constructor_init }}' - icon_enabled: '{{ utilities_constructor and repeat.item.icon is defined and repeat.item.icon is string and repeat.item.icon.split("mdi:")[1] in all_icons }}' + utilities_constructor: > + {{ utilities_constructor_init is defined and utilities_constructor_init }} + icon_enabled: > + {{ + utilities_constructor and + repeat.item.icon is defined and + repeat.item.icon is string and + repeat.item.icon.split("mdi:")[1] in all_icons + }} value1_enabled: > {{ repeat.item.value1 is defined and @@ -11302,7 +12069,13 @@ actions: repeat.item.value2.split(".") | count == 2 and (utilities_constructor or (trigger.entity_id == repeat.item.value2)) }} - label_enabled: '{{ utilities_constructor and repeat.item.label is defined and repeat.item.label is string and repeat.item.label | length > 0 }}' + label_enabled: > + {{ + utilities_constructor and + repeat.item.label is defined and + repeat.item.label is string and + repeat.item.label | length > 0 + }} - alias: Utilities - Display icon if: '{{ icon_enabled }}' then: @@ -11347,23 +12120,50 @@ actions: line_ref_state: > {{ states(repeat.item.line_ref) | float(0) - if repeat.item.line_ref is defined and repeat.item.line_ref is string and repeat.item.line_ref.split(".") | count == 2 + if + repeat.item.line_ref is defined and + repeat.item.line_ref is string and + repeat.item.line_ref.split(".") | count == 2 else 0 }} - direction: '{{ (((line_ref_state > 0) - (line_ref_state < 0)) * (-3 if repeat.item.line_inverted is defined and repeat.item.line_inverted else 3)) | int(0) }}' + direction: > + {{ + ( + ((line_ref_state > 0) - (line_ref_state < 0)) * + ( + -3 + if repeat.item.line_inverted is defined and repeat.item.line_inverted + else 3 + ) + ) | int(0) + }} - alias: Utilities - Display values if: '{{ value1_enabled or value2_enabled }}' then: - variables: value_enabled: '{{ value1_enabled }}' entity_id: '{{ repeat.item.value1 if value1_enabled else "" }}' - unit_of_measurement: '{{ state_attr(entity_id, "unit_of_measurement") | default("") if value1_enabled else "" }}' + unit_of_measurement: > + {{ + state_attr(entity_id, "unit_of_measurement") | default("") + if value1_enabled + else "" + }} - *variable_entity - variables: value1_val: &utilities_value_with_unit_and_translations > {{ ( - (states(entity_id, rounded=true) ~ (unit_of_measurement if unit_of_measurement is string and unit_of_measurement | length > 0 else "")) + ( + states(entity_id, rounded=true) ~ + ( + unit_of_measurement + if + unit_of_measurement is string and + unit_of_measurement | length > 0 + else "" + ) + ) if is_number(entity_state) else state_translated(entity_id) ) @@ -11372,7 +12172,12 @@ actions: }} value_enabled: '{{ value2_enabled }}' entity_id: '{{ repeat.item.value2 if value2_enabled else "" }}' - unit_of_measurement: '{{ state_attr(entity_id, "unit_of_measurement") | default("") if value2_enabled else "" }}' + unit_of_measurement: > + {{ + state_attr(entity_id, "unit_of_measurement") | default("") + if value2_enabled + else "" + }} - *variable_entity - variables: value2_val: *utilities_value_with_unit_and_translations @@ -11425,7 +12230,14 @@ actions: - '{{ utilities_constructor }}' then: - variables: - rgb565: '{{ int(((repeat.item.color[0] //(2**3)) *(2**11))+((repeat.item.color[1] //(2**2)) *(2**5))+(repeat.item.color[2] //(2**3))) }}' + rgb565: > + {{ + int( + ((repeat.item.color[0] //(2**3)) *(2**11))+ + ((repeat.item.color[1] //(2**2)) *(2**5))+ + (repeat.item.color[2] //(2**3)) + ) + }} - *delay_default - action: 'esphome.{{ nspanel_name }}_command' data: @@ -11463,19 +12275,30 @@ actions: sequence: - *variables_hardware - variables: - last_click_button: '{{ hardware.buttons.left if nspanel_event.component == "hw_bt_left" else hardware.buttons.right }}' + last_click_button: > + {{ + hardware.buttons.left + if nspanel_event.component == "hw_bt_left" + else hardware.buttons.right + }} entity_id: '{{ last_click_button.entity }}' - *variable_entity - choose: - alias: Long click - conditions: - - '{{ nspanel_event.command == "long_click" or entity_domain in ["alarm_control_panel", "climate", "media_player"] }}' + conditions: > + {{ + nspanel_event.command == "long_click" or + entity_domain in ["alarm_control_panel", "climate", "media_player"] + }} sequence: - choose: - alias: Default - conditions: - - '{{ last_click_button.hold_select == "Default" }}' - - '{{ entity_domain in ["alarm_control_panel", "climate", "cover", "fan", "light", "media_player"] }}' + conditions: > + {{ + last_click_button.hold_select == "Default" and + entity_domain in ["alarm_control_panel", "climate", "cover", + "fan", "light", "media_player"] + }} sequence: - variables: back_page: '{{ pages.home }}' @@ -11485,10 +12308,21 @@ actions: - *delay_default - action: 'esphome.{{ nspanel_name }}_entity_details_show' data: - entity_id: '{{ "embedded_climate" if entity_id == thermostat_embedded else entity_id }}' + entity_id: > + {{ + "embedded_climate" + if entity_id == thermostat_embedded + else entity_id + }} back_page: '{{ back_page }}' continue_on_error: true - - if: '{{ entity is defined and entity.icon is defined and entity.icon is string and entity.icon | length > 0 }}' + - if: > + {{ + entity is defined and + entity.icon is defined and + entity.icon is string and + entity.icon | length > 0 + }} then: - *delay_default - action: 'esphome.{{ nspanel_name }}_component_text' @@ -11497,7 +12331,13 @@ actions: component: icon_state txt: '{{ entity.icon }}' continue_on_error: true - - if: '{{ entity is defined and entity.name is defined and entity.name is string and entity.name | length > 0 }}' + - if: > + {{ + entity is defined and + entity.name is defined and + entity.name is string and + entity.name | length > 0 + }} then: - *delay_default - action: 'esphome.{{ nspanel_name }}_component_text' @@ -11507,35 +12347,71 @@ actions: txt: '{{ entity.name }}' continue_on_error: true - alias: Custom action - Left - conditions: '{{ last_click_button.hold_select == "Custom Action" and nspanel_event.component == "hw_bt_left" }}' + conditions: > + {{ + last_click_button.hold_select == "Custom Action" and + nspanel_event.component == "hw_bt_left" + }} sequence: !input left_button_hold_custom_action - alias: Custom action - Right - conditions: '{{ last_click_button.hold_select == "Custom Action" and nspanel_event.component == "hw_bt_right" }}' + conditions: > + {{ + last_click_button.hold_select == "Custom Action" and + nspanel_event.component == "hw_bt_right" + }} sequence: !input right_button_hold_custom_action - alias: Short click - conditions: - - '{{ nspanel_event.command == "short_click" and entity_domain not in ["alarm_control_panel", "climate", "media_player"] }}' + conditions: > + {{ + nspanel_event.command == "short_click" and + entity_domain not in ["alarm_control_panel", "climate", "media_player"] + }} sequence: - condition: '{{ last_click_button.entity | length > 0 }}' - - condition: '{{ nspanel_event.component != "hw_bt_left" or hardware.buttons.left.entity != relay01_entity }}' - - condition: '{{ nspanel_event.component != "hw_bt_right" or hardware.buttons.right.entity != relay02_entity }}' + - condition: > + {{ + nspanel_event.component != "hw_bt_left" or + hardware.buttons.left.entity != relay01_entity + }} + - condition: > + {{ + nspanel_event.component != "hw_bt_right" or + hardware.buttons.right.entity != relay02_entity + }} - &short_press-action_call alias: Short press - Action call sequence: - action: > - {% if entity_domain in ["cover"] - and states(last_click_button.entity) in ["opening", "closing"] - and state_attr(last_click_button.entity, "supported_features") | int(0) | bitwise_and(4) == 0 %} + {% if + entity_domain in ["cover"] and + states(last_click_button.entity) in ["opening", "closing"] and + state_attr(last_click_button.entity, "supported_features") + | int(0) + | bitwise_and(4) == 0 + %} {{ entity_domain }}.stop_cover - {% elif entity_domain in ["light", "switch", "cover", "input_boolean", "fan", "remote"] %} + {% elif + entity_domain in ["light", "switch", "cover", + "input_boolean", "fan", "remote"] + %} {{ entity_domain }}.toggle {% elif entity_domain in ["automation"] %} - {{ entity_domain }}.{{ domain_automation_button_action if domain_automation_button_action is string else "toggle"}} + {{ entity_domain }}.{{ + domain_automation_button_action + if domain_automation_button_action is string + else "toggle" + }} {% elif entity_domain in ["button", "input_button"] %} {{ entity_domain }}.press - {% elif entity_domain in ["lock"] and states(last_click_button.entity) in ["locked"] %} + {% elif + entity_domain in ["lock"] and + states(last_click_button.entity) in ["locked"] + %} {{ entity_domain }}.unlock - {% elif entity_domain in ["lock"] and states(last_click_button.entity) in ["unlocked"] %} + {% elif + entity_domain in ["lock"] and + states(last_click_button.entity) in ["unlocked"] + %} {{ entity_domain }}.lock {% elif entity_domain in ["scene", "script"] %} {{ entity_domain }}.turn_on @@ -11584,15 +12460,24 @@ actions: - choose: - alias: Long click conditions: - - '{{ nspanel_event.command == "long_click" or entity_domain in ["alarm_control_panel", "climate", "media_player"] }}' - - '{{ entity_domain in ["alarm_control_panel", "climate", "cover", "light", "fan", "media_player"] }}' + - > + {{ + nspanel_event.command == "long_click" or + entity_domain in ["alarm_control_panel", "climate", "media_player"] + }} + - > + {{ + entity_domain in ["alarm_control_panel", "climate", + "cover", "light", "fan", "media_player"] + }} sequence: - variables: back_page: '{{ nspanel_event.page }}' - *entity_details_show - alias: Short click conditions: - - '{{ nspanel_event.command == "short_click" and entity_domain not in ["alarm_control_panel", "climate", "media_player"] }}' + - '{{ nspanel_event.command == "short_click" }}' + - '{{ entity_domain not in ["alarm_control_panel", "climate", "media_player"] }}' - '{{ entity_domain not in ["unknown", "person", "binary_sensor", "sensor"] }}' sequence: - *short_press-action_call @@ -11603,7 +12488,13 @@ actions: sequence: - *climate-update_custom_buttons-variables - variables: - last_click_button: '{{ climate_custom_buttons | selectattr("component", "defined") | selectattr("component", "eq", nspanel_event.component) | list }}' + last_click_button: > + {{ + climate_custom_buttons + | selectattr("component", "defined") + | selectattr("component", "eq", nspanel_event.component) + | list + }} - condition: '{{ last_click_button | count >= 0 }}' - variables: last_click_button: '{{ last_click_button[0] }}' @@ -11640,7 +12531,13 @@ actions: - '{{ nspanel_event.page == pages.home }}' sequence: - variables: - last_click_button: '{{ home_page.custom_buttons | selectattr("component", "defined") | selectattr("component", "eq", nspanel_event.component) | list }}' + last_click_button: > + {{ + home_page.custom_buttons + | selectattr("component", "defined") + | selectattr("component", "eq", nspanel_event.component) + | list + }} continue_on_error: true - condition: '{{ last_click_button | count >= 0 }}' - variables: @@ -11655,8 +12552,14 @@ actions: {{ entity_domain in ["alarm_control_panel", "climate", "media_player"] or (entity_domain == "cover" and supported_features | bitwise_and(4) > 0) or - (entity_domain == "fan" and (supported_features | bitwise_and(1) > 0 or supported_features | bitwise_and(2) > 0)) or - (entity_domain == "light" and (color_mode_brightness or color_mode_color or color_mode_temp)) + ( + entity_domain == "fan" and + (supported_features | bitwise_and(1) > 0 or supported_features | bitwise_and(2) > 0) + ) or + ( + entity_domain == "light" and + (color_mode_brightness or color_mode_color or color_mode_temp) + ) }} then: - variables: @@ -11716,8 +12619,17 @@ actions: - Current Blueprint version: {{ blueprint_version }} - - Expected version: {{ nspanel_event.esphome if newest[0] == "esphome" else nspanel_event.tft }}, based on the panel **{{ - device_attr(nspanel_deviceid, "name") ~ ((" - " ~ nspanel_name) if nspanel_name != device_attr(nspanel_deviceid, "name") else "") }}**. + - Expected version: {{ + nspanel_event.esphome + if newest[0] == "esphome" + else nspanel_event.tft + }}, based on the panel **{{ + device_attr(nspanel_deviceid, "name") ~ + ( + (" - " ~ nspanel_name) + if nspanel_name != device_attr(nspanel_deviceid, "name") + else "" + ) }}**. --- **How to Resolve This Issue** @@ -11737,7 +12649,8 @@ actions: 7. Select "**Automations**" to reload the automations. - *For more detailed instructions, please refer to the online documentation: [How to Update Blueprint](https://github.com/Blackymas/NSPanel_HA_Blueprint/blob/main/docs/howto.md#update-blueprint).* + *For more detailed instructions, please refer to the online documentation: + [How to Update Blueprint](https://github.com/Blackymas/NSPanel_HA_Blueprint/blob/main/docs/howto.md#update-blueprint).* continue_on_error: true - alias: ESPHome is older conditions: @@ -11750,17 +12663,37 @@ actions: title: NSPanel ESPHome Needs Update message: > Your NSPanel ESPHome version is outdated for the panel **{{ - device_attr(nspanel_deviceid, "name") ~ ((" (" ~ nspanel_name ~ ")") if nspanel_name != device_attr(nspanel_deviceid, "name") else "") }}**. - - - Current ESPHome version: {{ nspanel_event.esphome if nspanel_event.esphome is string and nspanel_event.esphome | length > 0 else oldest[1] }} + device_attr(nspanel_deviceid, "name") ~ + ( + (" (" ~ nspanel_name ~ ")") + if nspanel_name != device_attr(nspanel_deviceid, "name") + else "" + ) }}**. + + - Current ESPHome version: {{ + nspanel_event.esphome + if nspanel_event.esphome is string and nspanel_event.esphome | length > 0 + else oldest[1] + }} - - Expected version: {{ blueprint_version if newest[0] == "blueprint" else nspanel_event.tft }} + - Expected version: {{ + blueprint_version + if newest[0] == "blueprint" + else nspanel_event.tft + }} **How to Resolve This Issue** 1. Go to your ESPHome Dashboard. - 2. Locate the panel named {{ device_attr(nspanel_deviceid, "name") ~ ((" (" ~ nspanel_name ~ ")") if nspanel_name != device_attr(nspanel_deviceid, "name") else "") }}. + 2. Locate the panel named {{ + device_attr(nspanel_deviceid, "name") ~ + ( + (" (" ~ nspanel_name ~ ")") + if nspanel_name != device_attr(nspanel_deviceid, "name") + else "" + ) + }}. 3. Click on the corresponding 3-dot menu. @@ -11771,7 +12704,8 @@ actions: 6. Select "**Wirelessly**". - *For more detailed instructions, please refer to the online documentation: [How to Update ESPHome](https://github.com/Blackymas/NSPanel_HA_Blueprint/blob/main/docs/howto.md#update-esphome).* + *For more detailed instructions, please refer to the online documentation: + [How to Update ESPHome](https://github.com/Blackymas/NSPanel_HA_Blueprint/blob/main/docs/howto.md#update-esphome).* continue_on_error: true - alias: TFT is older conditions: @@ -11784,24 +12718,40 @@ actions: title: NSPanel TFT Display Needs Update message: > The TFT version on your NSPanel is outdated for the panel **{{ - device_attr(nspanel_deviceid, "name") ~ ((" (" ~ nspanel_name ~ ")") if nspanel_name != device_attr(nspanel_deviceid, "name") else "") }}**. + device_attr(nspanel_deviceid, "name") ~ + ( + (" (" ~ nspanel_name ~ ")") + if nspanel_name != device_attr(nspanel_deviceid, "name") + else "" + ) + }}**. - - Current TFT version: {{ nspanel_event.tft if nspanel_event.tft is string and nspanel_event.tft | length > 0 else oldest[1] }} + - Current TFT version: {{ + nspanel_event.tft + if nspanel_event.tft is string and nspanel_event.tft | length > 0 + else oldest[1] + }} - - Expected version: {{ blueprint_version if newest[0] == "blueprint" else nspanel_event.esphome }} + - Expected version: {{ + blueprint_version + if newest[0] == "blueprint" + else nspanel_event.esphome + }} **How to Resolve This Issue** 1. Navigate to the [device page](/config/devices/device/{{ nspanel_deviceid }}). - 2. In the "**Configuration**" section, find the option labeled "**Update TFT Display - Model**". + 2. In the "**Configuration**" section, + find the option labeled "**Update TFT Display - Model**". 3. Click "**Update TFT Display**" to initiate the update process. 4. Please wait patiently until your panel restarts, indicating the update is complete. - *For more detailed instructions, please refer to the online documentation: [How to Update TFT](https://github.com/Blackymas/NSPanel_HA_Blueprint/blob/main/docs/howto.md#update-tft).* + *For more detailed instructions, please refer to the online documentation: + [How to Update TFT](https://github.com/Blackymas/NSPanel_HA_Blueprint/blob/main/docs/howto.md#update-tft).* continue_on_error: true - alias: Blueprint not detected conditions: @@ -11815,12 +12765,17 @@ actions: message: > The ESPHome is unable to verify the Blueprint version for the NSPanel. - - Panel Details: **{{ device_attr(nspanel_deviceid, "name") ~ (" (" ~ nspanel_name ~ ")") if nspanel_name != device_attr(nspanel_deviceid, "name") }}** + - Panel Details: **{{ + device_attr(nspanel_deviceid, "name") ~ + (" (" ~ nspanel_name ~ ")") + if nspanel_name != device_attr(nspanel_deviceid, "name") + }}** - Installed Blueprint Version: {{ blueprint_version }} - Troubleshooting steps and more information are available in the online documentation: [Panel startup issues - Blueprint is not detected](https://github.com/Blackymas/NSPanel_HA_Blueprint/blob/main/docs/error_initializing.md#blueprint-is-not-detected). + Troubleshooting steps and more information are available in the online documentation: + [Panel startup issues - Blueprint is not detected](https://github.com/Blackymas/NSPanel_HA_Blueprint/blob/main/docs/error_initializing.md#blueprint-is-not-detected). continue_on_error: true # yamllint enable rule:line-length - alias: All versions are the same @@ -11846,11 +12801,15 @@ actions: - '{{ nspanel_event.type == "generic"}}' sequence: - 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 + # rgb_color, brightness, color_temp + # This was kept until we find a solution to call with rgb_color directly from ESPHome + - alias: light settings conditions: - '{{ 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 }}' + - '{{ nspanel_event.entity is defined }}' + - '{{ nspanel_event.entity is string }}' + - '{{ nspanel_event.entity | length > 0 }}' sequence: - action: light.turn_on data: @@ -11882,9 +12841,24 @@ actions: - variables: nextion_inited: 'binary_sensor.{{ nspanel_name }}_nextion_display' - delay: > # Prevents all panels updating simultaneously in large systems - {% set entities_list = states.binary_sensor | selectattr("entity_id", "search", "nextion_display") | map(attribute="entity_id") | list %} - {{ (4 * entities_list.index(nextion_inited)) if (entities_list | count > 0 and nextion_inited in entities_list) else 0 }} - - if: '{{ states.sensor | selectattr("entity_id", "eq", currentpage) | list | count > 0 }}' + {% set entities_list = + states.binary_sensor + | selectattr("entity_id", "search", "nextion_display") + | map(attribute="entity_id") + | list + %} + {{ + (4 * entities_list.index(nextion_inited)) + if (entities_list | count > 0 and nextion_inited in entities_list) + else 0 + }} + - if: > + {{ + states.sensor + | selectattr("entity_id", "eq", currentpage) + | list + | count > 0 + }} then: - action: persistent_notification.dismiss data: @@ -11898,7 +12872,10 @@ actions: message: > The sensor "Current Page" (`{{ currentpage }}`) is unavailable. - - Panel: {{ device_attr(nspanel_deviceid, "name") ~ (" (" ~ nspanel_name ~ ")") if nspanel_name != device_attr(nspanel_deviceid, "name") }} + - Panel: {{ + device_attr(nspanel_deviceid, "name") ~ (" (" ~ nspanel_name ~ ")") + if nspanel_name != device_attr(nspanel_deviceid, "name") + }} - Blueprint version: {{ blueprint_version }} @@ -11909,13 +12886,15 @@ actions: 1. Go to the [device page](/config/devices/device/{{ nspanel_deviceid }}) - 2. Find the sensor "Current page" under the "Sensors" area (it might be in the "sensors not shown" group) + 2. Find the sensor "Current page" under the "Sensors" area + (it might be in the "sensors not shown" group) 3. Enable the sensor 4. Wait a bit until the sensor starts providing a value (it shouldn't take more than half minute) - 5. Go to [Developer Tools](/developer-tools/yaml) and click the button "Automations" to reload your automations + 5. Go to [Developer Tools](/developer-tools/yaml) and + click the button "Automations" to reload your automations continue_on_error: true ##### Update global settings (as user may have changed something) ##### @@ -11946,7 +12925,8 @@ actions: - condition: or conditions: - '{{ 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) }}' + - '{{ pages.current in [pages.light, pages.cover, pages.climate, pages.fan, pages.alarm] }}' + - '{{ trigger.entity_id == states(detailed_entity) }}' sequence: - choose: - alias: Button pages @@ -12077,9 +13057,27 @@ actions: - '{{ pages.current == pages.utilities }}' sequence: - variables: - list1: '{{ pages_utilities.groups | selectattr("value1", "defined") | selectattr("value1", "eq", trigger.entity_id) | list }}' - list2: '{{ pages_utilities.groups | selectattr("value2", "defined") | selectattr("value2", "eq", trigger.entity_id) | list }}' - list3: '{{ pages_utilities.groups | selectattr("line_ref", "defined") | selectattr("line_ref", "eq", trigger.entity_id) | list }}' + list1: > + {{ + pages_utilities.groups + | selectattr("value1", "defined") + | selectattr("value1", "eq", trigger.entity_id) + | list + }} + list2: > + {{ + pages_utilities.groups + | selectattr("value2", "defined") + | selectattr("value2", "eq", trigger.entity_id) + | list + }} + list3: > + {{ + pages_utilities.groups + | selectattr("line_ref", "defined") + | selectattr("line_ref", "eq", trigger.entity_id) + | list + }} full_list: '{{ list1 + list2 + list3 }}' groups: '{{ full_list | map(attribute="name") | unique | list }}' - repeat: @@ -12104,7 +13102,12 @@ actions: - home_custom_buttons sequence: - variables: - trigger_entity_id: '{{ trigger.entity_id if trigger.entity_id is defined else trigger.event.data.entity_id }}' + trigger_entity_id: > + {{ + trigger.entity_id + if trigger.entity_id is defined + else trigger.event.data.entity_id + }} - choose: - alias: "Home page" conditions: @@ -12220,7 +13223,11 @@ actions: - action: 'esphome.{{ nspanel_name }}_set_number' data: component: hw_button_state - val: '{{ (1 if button_state else 2) * (1 if trigger.id in ["left_button_state", "left_button_alt_state"] else 4) }}' + val: > + {{ + (1 if button_state else 2) * + (1 if trigger.id in ["left_button_state", "left_button_alt_state"] else 4) + }} continue_on_error: true - delay: milliseconds: 250 @@ -12232,7 +13239,11 @@ actions: - action: 'esphome.{{ nspanel_name }}_set_number' data: component: hw_button_state - val: '{{ (1 if button_state_new else 2) * (1 if trigger.id in ["left_button_state", "left_button_alt_state"] else 4) }}' + val: > + {{ + (1 if button_state_new else 2) * + (1 if trigger.id in ["left_button_state", "left_button_alt_state"] else 4) + }} continue_on_error: true ##### OUTDOOR TEMP - entity ##### @@ -12260,7 +13271,10 @@ actions: - '{{ pages.current == pages.home }}' - > {{ - (trigger.id == "weather_state_change" and trigger.event.data.new_state.state not in enum.states.unknown) or + ( + trigger.id == "weather_state_change" and + trigger.event.data.new_state.state not in enum.states.unknown + ) or (trigger.id == "sun_state_change" and trigger.to_state.state not in enum.states.unknown) }} sequence: