# yaml-language-server: $schema=null #:########################################################################################:# # TITLE: NSPANEL LOUNGE CONTROLLER # zorruno.com Home Assistant package #:########################################################################################:# # VERSIONS: # V1.5 2026-05-19 # - Added Reading button brightness display. # - Reading brightness is shown as the highest brightness percentage of either # couch spot light. # - Changed Balanced button icon to mdi:scale / \uE472. # - Added startup panel page refresh before full button state refresh. # # V1.4 2026-05-19 # - Changed button highlighting to targeted updates. # - Remembered scene changes update only the old scene button and new scene button. # - Reading/Dining changes update only the Reading and Dining buttons. # - Full refresh is only used at HA start or when manually called. # - ON icon colour is black [0, 0, 0]. # - OFF icon colour is white [255, 255, 255]. # # V1.3 2026-05-19 # - Tested page refresh method, but it did not reliably refresh remembered scenes. # # V1.2 2026-05-19 # - Added explicit NSPanel button refresh actions using esphome.esp_nspanel2lounge_button. # - Button states were pushed to the NSPanel when lounge_last_scene or the # Reading/Dining light states changed. # # V1.1 2026-05-18 # - Added template switches so remembered lighting scenes can stay highlighted # on the NSPanel button page. # - Updated Blueprint button entities from script.* to switch.*. # # V1.0 2026-05-18 # - Initial NSPanel Lounge Controller package using NSPanel Easy Blueprint. #:########################################################################################:# # PURPOSE: # - Configures the Lounge NSPanel Easy button page. # - Provides Home Assistant script wrappers for lounge lighting scene actions. # - Provides template switches for NSPanel button state/highlighting. # - Pushes targeted NSPanel button highlight updates when relevant states change. #:########################################################################################:# # OPERATION NOTES: # - The NSPanel display is configured by the NSPanel Easy Blueprint automation. # - The screen buttons point to switch.nspanel_lounge_scene_* entities. # - Remembered scenes are highlighted from input_text.lounge_last_scene. # - Reading On/Off is highlighted from either couch spot light being on. # - Reading On/Off shows the highest couch spot brightness percentage. # - Dining On/Off is highlighted from the dining table light being on. # - Pressing any NSPanel touch button activates the assigned scene/action. # - Normal remembered scene transitions update only: # a) the previous remembered scene button to OFF # b) the new remembered scene button to ON #:########################################################################################:# # DEPENDENCIES: # - script.lounge_set_scene # - input_text.lounge_last_scene # - light.esp_lounge6chdimmer_couch_spots_left # - light.esp_lounge6chdimmer_couch_spots_right # - light.esp_lounge6chdimmer_dining_table_light # - NSPanel Easy Blueprint: # edwardtfn/nspanel_easy_blueprint.yaml # - ESPHome actions: # esphome.esp_nspanel2lounge_button # esphome.esp_nspanel2lounge_command #:########################################################################################:# # NOTES: # - This is Home Assistant package YAML, not ESPHome YAML. # - The nspanel_name value is the Home Assistant device ID selected by the # Blueprint dropdown. Do not replace it with an entity_id or ESPHome hostname. # - The icon values used by esphome.esp_nspanel2lounge_button are HASP/Nextion # icon codepoints, not mdi: icon names. #:########################################################################################:# #:########################################################################################:# # AUTOMATIONS #:########################################################################################:# automation: #:######################################################################################:# # AUTOMATION: NSPanel Easy Blueprint Instance #:######################################################################################:# - id: nspanel_lounge_controller alias: "NSPanel Lounge Controller" description: "NSPanel Easy configuration for the lounge lighting scene panel." use_blueprint: path: edwardtfn/nspanel_easy_blueprint.yaml input: nspanel_name: 369e58c3779ff3dd9a0b4c59fadeac4f ######################################################################## # BUTTON PAGE 01: Lounge Lighting Scenes ######################################################################## button_page01_label: Lounge Lighting Scenes button_pages_icon_size: "10" entity01: switch.nspanel_lounge_scene_bright entity01_name: "Bright" entity01_icon: mdi:brightness-7 entity01_confirm: false entity02: switch.nspanel_lounge_scene_tv_general entity02_name: "TV General" entity02_icon: mdi:television entity02_confirm: false entity03: switch.nspanel_lounge_scene_movie entity03_name: "Movie" entity03_icon: mdi:movie-open entity03_confirm: false entity04: switch.nspanel_lounge_scene_balanced entity04_name: "Balance" entity04_icon: mdi:scale entity04_confirm: false entity05: switch.nspanel_lounge_scene_warm_cozy entity05_name: "Warm Cozy" entity05_icon: mdi:fireplace entity05_confirm: false entity06: switch.nspanel_lounge_scene_reading entity06_name: "Reading On/Off" entity06_icon: mdi:book-open-page-variant entity06_confirm: false entity07: switch.nspanel_lounge_scene_dining entity07_name: "Dining On/Off" entity07_icon: mdi:silverware-fork-knife entity07_confirm: false entity08: switch.nspanel_lounge_scene_all_off entity08_name: "All Off" entity08_icon: mdi:power entity08_confirm: false mode: single #:######################################################################################:# # AUTOMATION: Refresh Remembered Scene Button Highlights # # Only updates the previous remembered scene button and the new remembered # scene button when input_text.lounge_last_scene changes. #:######################################################################################:# - id: nspanel_lounge_refresh_remembered_scene_buttons alias: "NSPanel Lounge - Refresh Remembered Scene Buttons" description: "Update only the old and new remembered scene buttons on the NSPanel." mode: restart trigger: - platform: state entity_id: input_text.lounge_last_scene action: - delay: milliseconds: 500 - variables: old_scene: "{{ trigger.from_state.state if trigger.from_state is not none else '' }}" new_scene: "{{ trigger.to_state.state if trigger.to_state is not none else states('input_text.lounge_last_scene') }}" remembered_scenes: - "Bright" - "TV General" - "Balanced" - "Movie" - "Warm Cozy" - "All Off" - choose: - conditions: "{{ old_scene in remembered_scenes and old_scene != new_scene }}" sequence: - action: script.nspanel_lounge_push_scene_button_state data: scene_name: "{{ old_scene }}" button_state: false - delay: milliseconds: 100 - choose: - conditions: "{{ new_scene in remembered_scenes }}" sequence: - action: script.nspanel_lounge_push_scene_button_state data: scene_name: "{{ new_scene }}" button_state: true #:######################################################################################:# # AUTOMATION: Refresh Reading And Dining Button Highlights # # Reading/Dining are toggle/action scenes, so they are updated from the real # light states rather than input_text.lounge_last_scene. #:######################################################################################:# - id: nspanel_lounge_refresh_toggle_scene_buttons alias: "NSPanel Lounge - Refresh Toggle Scene Buttons" description: "Update Reading and Dining buttons when their lights change." mode: restart trigger: - platform: state entity_id: - light.esp_lounge6chdimmer_couch_spots_left - light.esp_lounge6chdimmer_couch_spots_right - light.esp_lounge6chdimmer_dining_table_light - platform: state entity_id: - light.esp_lounge6chdimmer_couch_spots_left - light.esp_lounge6chdimmer_couch_spots_right - light.esp_lounge6chdimmer_dining_table_light attribute: brightness action: - delay: milliseconds: 500 - action: script.nspanel_lounge_push_scene_button_state data: scene_name: "Reading On/Off" button_state: >- {{ ( is_state('light.esp_lounge6chdimmer_couch_spots_left', 'on') and (state_attr('light.esp_lounge6chdimmer_couch_spots_left', 'brightness') | int(0)) > 0 ) or ( is_state('light.esp_lounge6chdimmer_couch_spots_right', 'on') and (state_attr('light.esp_lounge6chdimmer_couch_spots_right', 'brightness') | int(0)) > 0 ) }} - delay: milliseconds: 100 - action: script.nspanel_lounge_push_scene_button_state data: scene_name: "Dining On/Off" button_state: >- {{ is_state('light.esp_lounge6chdimmer_dining_table_light', 'on') and (state_attr('light.esp_lounge6chdimmer_dining_table_light', 'brightness') | int(0)) > 0 }} #:######################################################################################:# # AUTOMATION: Initial NSPanel Button Refresh # # Full refresh happens when HA starts, or when the NSPanel comes back online. # Normal scene changes update only the required buttons. #:######################################################################################:# - id: nspanel_lounge_refresh_all_buttons_on_start alias: "NSPanel Lounge - Refresh All Buttons On Start" description: "Refresh all NSPanel lounge buttons when HA starts or the panel reconnects." mode: restart trigger: - platform: homeassistant event: start - platform: state entity_id: number.lounge_nspanel_touchscreen_display_brightness from: "unavailable" - platform: state entity_id: number.lounge_nspanel_touchscreen_display_brightness from: "unknown" action: - delay: seconds: 20 - action: esphome.esp_nspanel2lounge_command data: cmd: "page buttonpage01" - delay: seconds: 1 - action: script.nspanel_lounge_refresh_all_button_states #:########################################################################################:# # SCRIPTS #:########################################################################################:# script: #:######################################################################################:# # SCRIPTS: NSPanel Lounge Scene Button Actions #:######################################################################################:# nspanel_lounge_scene_bright: alias: "NSPanel Lounge Scene - Bright" mode: single sequence: - action: script.lounge_set_scene data: scene_name: "Bright" nspanel_lounge_scene_tv_general: alias: "NSPanel Lounge Scene - TV General" mode: single sequence: - action: script.lounge_set_scene data: scene_name: "TV General" nspanel_lounge_scene_movie: alias: "NSPanel Lounge Scene - Movie" mode: single sequence: - action: script.lounge_set_scene data: scene_name: "Movie" nspanel_lounge_scene_balanced: alias: "NSPanel Lounge Scene - Balanced" mode: single sequence: - action: script.lounge_set_scene data: scene_name: "Balanced" nspanel_lounge_scene_warm_cozy: alias: "NSPanel Lounge Scene - Warm Cozy" mode: single sequence: - action: script.lounge_set_scene data: scene_name: "Warm Cozy" nspanel_lounge_scene_reading: alias: "NSPanel Lounge Scene - Reading" mode: single sequence: - action: script.lounge_set_scene data: scene_name: "Reading On/Off" nspanel_lounge_scene_dining: alias: "NSPanel Lounge Scene - Dining" mode: single sequence: - action: script.lounge_set_scene data: scene_name: "Dining On/Off" nspanel_lounge_scene_all_off: alias: "NSPanel Lounge Scene - All Off" mode: single sequence: - action: script.lounge_set_scene data: scene_name: "All Off" #:######################################################################################:# # SCRIPT: Push One NSPanel Button State # # ON state: # - Button highlighted # - Icon colour black [0, 0, 0] # # OFF state: # - Button not highlighted # - Icon colour white [255, 255, 255] #:######################################################################################:# nspanel_lounge_push_button_state: alias: "NSPanel Lounge - Push Button State" mode: queued max: 20 fields: button_id: description: "NSPanel button id, for example button01" button_state: description: "True for highlighted, false for normal" icon_code: description: "HASwitchPlate/Nextion icon codepoint" button_label: description: "Button label text" button_bri: description: "Optional brightness/value text shown on the NSPanel button" sequence: - variables: button_is_on: >- {{ button_state in [true, 'true', 'True', 'on', 'On', '1', 1] }} button_bri_text: "{{ button_bri if button_bri is defined else '' }}" - choose: - conditions: "{{ button_is_on }}" sequence: - action: esphome.esp_nspanel2lounge_button data: page: buttonpage01 id: "{{ button_id }}" state: true icon: "{{ icon_code }}" icon_color: - 0 - 0 - 0 icon_font: 10 bri: "{{ button_bri_text }}" label: "{{ button_label }}" is_page_render: false default: - action: esphome.esp_nspanel2lounge_button data: page: buttonpage01 id: "{{ button_id }}" state: false icon: "{{ icon_code }}" icon_color: - 255 - 255 - 255 icon_font: 10 bri: "{{ button_bri_text }}" label: "{{ button_label }}" is_page_render: false #:######################################################################################:# # SCRIPT: Push One Scene Button State # # Maps scene/action names to NSPanel button ids, labels and icon codepoints. #:######################################################################################:# nspanel_lounge_push_scene_button_state: alias: "NSPanel Lounge - Push Scene Button State" mode: queued max: 20 fields: scene_name: description: "Lounge scene/action name" button_state: description: "True for highlighted, false for normal" sequence: - choose: - conditions: "{{ scene_name == 'Bright' }}" sequence: - action: script.nspanel_lounge_push_button_state data: button_id: button01 button_state: "{{ button_state }}" icon_code: "\uE0E0" button_label: "Bright" button_bri: "" - conditions: "{{ scene_name == 'TV General' }}" sequence: - action: script.nspanel_lounge_push_button_state data: button_id: button02 button_state: "{{ button_state }}" icon_code: "\uE502" button_label: "TV General" button_bri: "" - conditions: "{{ scene_name == 'Movie' }}" sequence: - action: script.nspanel_lounge_push_button_state data: button_id: button03 button_state: "{{ button_state }}" icon_code: "\uEFCE" button_label: "Movie" button_bri: "" - conditions: "{{ scene_name == 'Balanced' }}" sequence: - action: script.nspanel_lounge_push_button_state data: button_id: button04 button_state: "{{ button_state }}" icon_code: "\uE472" button_label: "Balance" button_bri: "" - conditions: "{{ scene_name == 'Warm Cozy' }}" sequence: - action: script.nspanel_lounge_push_button_state data: button_id: button05 button_state: "{{ button_state }}" icon_code: "\uEE2E" button_label: "Warm Cozy" button_bri: "" - conditions: "{{ scene_name == 'Reading On/Off' }}" sequence: - action: script.nspanel_lounge_push_button_state data: button_id: button06 button_state: "{{ button_state }}" icon_code: "\uE5DA" button_label: "Reading On/Off" button_bri: >- {% set left_on = is_state('light.esp_lounge6chdimmer_couch_spots_left', 'on') %} {% set right_on = is_state('light.esp_lounge6chdimmer_couch_spots_right', 'on') %} {% set left_raw = state_attr('light.esp_lounge6chdimmer_couch_spots_left', 'brightness') | int(0) if left_on else 0 %} {% set right_raw = state_attr('light.esp_lounge6chdimmer_couch_spots_right', 'brightness') | int(0) if right_on else 0 %} {% set left_pct = ((left_raw / 255) * 100) | round(0) | int %} {% set right_pct = ((right_raw / 255) * 100) | round(0) | int %} {% set reading_pct = [left_pct, right_pct] | max %} {% if reading_pct > 0 %}{{ reading_pct }}%{% else %}{% endif %} - conditions: "{{ scene_name == 'Dining On/Off' }}" sequence: - action: script.nspanel_lounge_push_button_state data: button_id: button07 button_state: "{{ button_state }}" icon_code: "\uEA70" button_label: "Dining On/Off" button_bri: "" - conditions: "{{ scene_name == 'All Off' }}" sequence: - action: script.nspanel_lounge_push_button_state data: button_id: button08 button_state: "{{ button_state }}" icon_code: "\uE425" button_label: "All Off" button_bri: "" #:######################################################################################:# # SCRIPT: Refresh All NSPanel Lounge Button States # # Use this manually after a panel restart, or automatically once at HA start. # Normal scene changes do not call this script. #:######################################################################################:# nspanel_lounge_refresh_all_button_states: alias: "NSPanel Lounge - Refresh All Button States" mode: restart sequence: - action: script.nspanel_lounge_push_scene_button_state data: scene_name: "Bright" button_state: "{{ is_state('switch.nspanel_lounge_scene_bright', 'on') }}" - delay: milliseconds: 100 - action: script.nspanel_lounge_push_scene_button_state data: scene_name: "TV General" button_state: "{{ is_state('switch.nspanel_lounge_scene_tv_general', 'on') }}" - delay: milliseconds: 100 - action: script.nspanel_lounge_push_scene_button_state data: scene_name: "Movie" button_state: "{{ is_state('switch.nspanel_lounge_scene_movie', 'on') }}" - delay: milliseconds: 100 - action: script.nspanel_lounge_push_scene_button_state data: scene_name: "Balanced" button_state: "{{ is_state('switch.nspanel_lounge_scene_balanced', 'on') }}" - delay: milliseconds: 100 - action: script.nspanel_lounge_push_scene_button_state data: scene_name: "Warm Cozy" button_state: "{{ is_state('switch.nspanel_lounge_scene_warm_cozy', 'on') }}" - delay: milliseconds: 100 - action: script.nspanel_lounge_push_scene_button_state data: scene_name: "Reading On/Off" button_state: "{{ is_state('switch.nspanel_lounge_scene_reading', 'on') }}" - delay: milliseconds: 100 - action: script.nspanel_lounge_push_scene_button_state data: scene_name: "Dining On/Off" button_state: "{{ is_state('switch.nspanel_lounge_scene_dining', 'on') }}" - delay: milliseconds: 100 - action: script.nspanel_lounge_push_scene_button_state data: scene_name: "All Off" button_state: "{{ is_state('switch.nspanel_lounge_scene_all_off', 'on') }}" #:######################################################################################:# # SCRIPT: Compatibility Wrapper # # Older versions used this script name. Keep it as a manual full refresh. #:######################################################################################:# nspanel_lounge_refresh_button_states: alias: "NSPanel Lounge - Refresh Button States" mode: restart sequence: - action: script.nspanel_lounge_refresh_all_button_states #:########################################################################################:# # TEMPLATE SWITCHES: NSPANEL BUTTON STATE AND HIGHLIGHTING #:########################################################################################:# template: - switch: ########################################################################## # Remembered scenes # These switches stay on when input_text.lounge_last_scene matches the # last remembered scene name. This allows the NSPanel button to remain # highlighted for the selected remembered scene. ########################################################################## - name: "NSPanel Lounge Scene Bright" unique_id: nspanel_lounge_scene_switch_bright state: "{{ is_state('input_text.lounge_last_scene', 'Bright') }}" turn_on: - action: script.lounge_set_scene data: scene_name: "Bright" turn_off: - action: script.lounge_set_scene data: scene_name: "Bright" - name: "NSPanel Lounge Scene TV General" unique_id: nspanel_lounge_scene_switch_tv_general state: "{{ is_state('input_text.lounge_last_scene', 'TV General') }}" turn_on: - action: script.lounge_set_scene data: scene_name: "TV General" turn_off: - action: script.lounge_set_scene data: scene_name: "TV General" - name: "NSPanel Lounge Scene Balanced" unique_id: nspanel_lounge_scene_switch_balanced state: "{{ is_state('input_text.lounge_last_scene', 'Balanced') }}" turn_on: - action: script.lounge_set_scene data: scene_name: "Balanced" turn_off: - action: script.lounge_set_scene data: scene_name: "Balanced" - name: "NSPanel Lounge Scene Movie" unique_id: nspanel_lounge_scene_switch_movie state: "{{ is_state('input_text.lounge_last_scene', 'Movie') }}" turn_on: - action: script.lounge_set_scene data: scene_name: "Movie" turn_off: - action: script.lounge_set_scene data: scene_name: "Movie" - name: "NSPanel Lounge Scene Warm Cozy" unique_id: nspanel_lounge_scene_switch_warm_cozy state: "{{ is_state('input_text.lounge_last_scene', 'Warm Cozy') }}" turn_on: - action: script.lounge_set_scene data: scene_name: "Warm Cozy" turn_off: - action: script.lounge_set_scene data: scene_name: "Warm Cozy" - name: "NSPanel Lounge Scene All Off" unique_id: nspanel_lounge_scene_switch_all_off state: "{{ is_state('input_text.lounge_last_scene', 'All Off') }}" turn_on: - action: script.lounge_set_scene data: scene_name: "All Off" turn_off: - action: script.lounge_set_scene data: scene_name: "All Off" ########################################################################## # Toggle/action scenes # These are excluded from input_text.lounge_last_scene, so their displayed # state comes from the actual light entities they control. ########################################################################## - name: "NSPanel Lounge Scene Reading" unique_id: nspanel_lounge_scene_switch_reading state: >- {{ ( is_state('light.esp_lounge6chdimmer_couch_spots_left', 'on') and (state_attr('light.esp_lounge6chdimmer_couch_spots_left', 'brightness') | int(0)) > 0 ) or ( is_state('light.esp_lounge6chdimmer_couch_spots_right', 'on') and (state_attr('light.esp_lounge6chdimmer_couch_spots_right', 'brightness') | int(0)) > 0 ) }} turn_on: - action: script.lounge_set_scene data: scene_name: "Reading On/Off" turn_off: - action: script.lounge_set_scene data: scene_name: "Reading On/Off" - name: "NSPanel Lounge Scene Dining" unique_id: nspanel_lounge_scene_switch_dining state: >- {{ is_state('light.esp_lounge6chdimmer_dining_table_light', 'on') and (state_attr('light.esp_lounge6chdimmer_dining_table_light', 'brightness') | int(0)) > 0 }} turn_on: - action: script.lounge_set_scene data: scene_name: "Dining On/Off" turn_off: - action: script.lounge_set_scene data: scene_name: "Dining On/Off"