From 48c4ec794144ccf5fad3b64a907df00862ecfd14 Mon Sep 17 00:00:00 2001 From: aderusha Date: Wed, 3 Mar 2021 07:21:06 -0500 Subject: [PATCH] Add blueprints and HMI --- .../blueprints/hasp_Activate_Page.yaml | 125 ++++ .../blueprints/hasp_Core_Functionality.yaml | 30 +- .../hasp_Create_Device_Triggers.yaml | 17 +- .../hasp_Display_Alarm_Control_page7.yaml | 19 +- .../hasp_Display_Calendar_with_Icon.yaml | 8 +- .../blueprints/hasp_Display_Clock.yaml | 17 +- .../hasp_Display_Clock_with_Icon.yaml | 8 +- .../hasp_Display_Dimmer_with_Icon.yaml | 8 +- ...asp_Display_Entity_State_or_Attribute.yaml | 425 ++++++++++++++ .../hasp_Display_Media_Control_page8.yaml | 353 ++++++++++++ ...play_Temperature_with_Icon_and_Colors.yaml | 11 +- .../blueprints/hasp_Display_Template.yaml | 396 +++++++++++++ .../blueprints/hasp_Display_Text.yaml | 345 +++++++++++ .../blueprints/hasp_Display_Toggle.yaml | 535 ++++++++++++++++++ .../hasp_Display_Volume_Control_page8.yaml | 200 +++++++ .../hasp_Display_Weather_Condition.yaml | 360 ++++++++++++ ...p_Display_Weather_Condition_with_Icon.yaml | 22 +- .../hasp_Display_Weather_Forecast.yaml | 394 +++++++++++++ .../blueprints/hasp_Perform_Action.yaml | 111 ++++ LICENSE | 29 +- Nextion_HMI/HASwitchPlate-Enhanced.tft | Bin 3255092 -> 3256372 bytes Nextion_HMI/HASwitchPlate-Inverted.tft | Bin 3189556 -> 3190836 bytes Nextion_HMI/HASwitchPlate-TJC.HMI | Bin 3964195 -> 3964430 bytes Nextion_HMI/HASwitchPlate-TJC.tft | Bin 3189556 -> 3190836 bytes Nextion_HMI/HASwitchPlate.HMI | Bin 4024291 -> 3964910 bytes Nextion_HMI/HASwitchPlate.tft | Bin 3190836 -> 3190836 bytes .../hasp_Display_Text_and_Activate_Page.png | Bin 2391 -> 0 bytes .../hasp_Display_Text_and_Trigger_Scene.png | Bin 1935 -> 0 bytes update/version-insecure.json | 18 - update/version.json | 10 +- 30 files changed, 3355 insertions(+), 86 deletions(-) create mode 100644 Home_Assistant/blueprints/hasp_Activate_Page.yaml create mode 100644 Home_Assistant/blueprints/hasp_Display_Entity_State_or_Attribute.yaml create mode 100644 Home_Assistant/blueprints/hasp_Display_Media_Control_page8.yaml create mode 100644 Home_Assistant/blueprints/hasp_Display_Template.yaml create mode 100644 Home_Assistant/blueprints/hasp_Display_Text.yaml create mode 100644 Home_Assistant/blueprints/hasp_Display_Toggle.yaml create mode 100644 Home_Assistant/blueprints/hasp_Display_Volume_Control_page8.yaml create mode 100644 Home_Assistant/blueprints/hasp_Display_Weather_Condition.yaml create mode 100644 Home_Assistant/blueprints/hasp_Display_Weather_Forecast.yaml create mode 100644 Home_Assistant/blueprints/hasp_Perform_Action.yaml delete mode 100644 images/hasp_Display_Text_and_Activate_Page.png delete mode 100644 images/hasp_Display_Text_and_Trigger_Scene.png delete mode 100644 update/version-insecure.json diff --git a/Home_Assistant/blueprints/hasp_Activate_Page.yaml b/Home_Assistant/blueprints/hasp_Activate_Page.yaml new file mode 100644 index 0000000..c4f018e --- /dev/null +++ b/Home_Assistant/blueprints/hasp_Activate_Page.yaml @@ -0,0 +1,125 @@ +blueprint: + name: "HASP p[x].b[y] activates a page" + description: | + + # Description + + A button on the HASP will activate a page when pressed. Can be combined on a button with another blueprint which displays text. + + ## HASP Page and Button Reference + + The images below show each available HASP page along with the layout of available button objects. + +
+ + | Page 0 | Pages 1-3 | Pages 4-5 | + |--------|-----------|-----------| + | ![Page 0](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p0_Init_Screen.png) | ![Pages 1-3](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p1-p3_4buttons.png) | ![Pages 4-5](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p4-p5_3sliders.png) | + + | Page 6 | Page 7 | Page 8 | + |--------|--------|--------| + | ![Page 6](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p6_8buttons.png) | ![Page 7](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p7_12buttons.png) | ![Page 8](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p8_5buttons+1slider.png) | + + | Page 9 | Page 10 | Page 11 | + |--------|---------|---------| + | ![Page 9](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p9_9buttons.png) | ![Page 10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p10_5buttons.png) | ![Page 11](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p11_1button+1slider.png) + +
+ + source_url: "https://github.com/HASwitchPlate/Blueprints/blob/main/hasp_Activate_Page.yaml" + domain: automation + input: + haspdevice: + name: "HASP Device" + description: "Select the HASP device" + selector: + device: + integration: mqtt + manufacturer: "HASwitchPlate" + model: "HASPone v1.0.0" + hasppage: + name: "HASP Page" + description: "Select the HASP page (1-11) for this page button. Refer to the HASP Page and Button reference above." + default: 1 + selector: + number: + min: 1 + max: 11 + mode: slider + unit_of_measurement: page + haspbutton: + name: "HASP Button" + description: "Select the HASP button for this page button. Refer to the HASP Page and Button reference above." + default: 4 + selector: + number: + min: 4 + max: 15 + mode: slider + unit_of_measurement: button + targetpage: + name: "Page to activate" + description: "Select a destination page for this button to activate." + default: 1 + selector: + number: + min: 1 + max: 11 + mode: slider + unit_of_measurement: page + +mode: parallel +max_exceeded: silent + +variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + hasppage: !input hasppage + haspbutton: !input haspbutton + targetpage: !input targetpage + pagecommandtopic: '{{ "hasp/" ~ haspname ~ "/command/page" }}' + jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' + +trigger_variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + haspsensor: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} + {{ entity }} + {{ break }} + {%- endif -%} + {%- endfor -%} + jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' + hasppage: !input hasppage + haspbutton: !input haspbutton + haspobject: '{{ "p[" ~ hasppage ~ "].b[" ~ haspbutton ~ "]" }}' + buttonjsonpayload: '{"event_type":"button_short_press","event":"{{haspobject}}","value":"ON"}' + +trigger: + - platform: mqtt + topic: "{{jsontopic}}" + payload: "{{buttonjsonpayload}}" + +condition: + - condition: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + +action: + - service: mqtt.publish + data: + topic: "{{pagecommandtopic}}" + payload: "{{targetpage}}" + diff --git a/Home_Assistant/blueprints/hasp_Core_Functionality.yaml b/Home_Assistant/blueprints/hasp_Core_Functionality.yaml index b799a82..104106a 100644 --- a/Home_Assistant/blueprints/hasp_Core_Functionality.yaml +++ b/Home_Assistant/blueprints/hasp_Core_Functionality.yaml @@ -24,7 +24,7 @@ blueprint: | Page 9 | Page 10 | Page 11 | |--------|---------|---------| - | ![Page 9](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p9_9buttons.png) | ![Page 10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p10_5buttons.png) | ![Page 11](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p11_1button.png) + | ![Page 9](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p9_9buttons.png) | ![Page 10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p10_5buttons.png) | ![Page 11](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p11_1button+1slider.png) @@ -102,6 +102,7 @@ blueprint: min: 0 max: 11 mode: slider + unit_of_measurement: page page2text: name: "Page select button 2 text" description: "Enter text to appear on the center page select button #2. If page scrolling is enabled, use the Page Names list below." @@ -135,6 +136,7 @@ blueprint: min: 0 max: 11 mode: slider + unit_of_measurement: page page3text: name: "Page select button 3 text" description: "Enter text to appear on the right-most page select button #3" @@ -168,6 +170,7 @@ blueprint: min: 0 max: 11 mode: slider + unit_of_measurement: page page_scroll: name: "Enable page scrolling instead of page select" description: "If enabled, page buttons 1 and 3 will scroll up and down through available pages. The middle page button 2 will continue to select its assigned page number, but the label for page button 2 will be determined based on the Page Names defined below." @@ -318,7 +321,13 @@ trigger_variables: {{ break }} {%- endif -%} {%- endfor -%} - statetopic: '{{ "hasp/" ~ haspname ~ "/state" }}' + haspsensor: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} + {{ entity }} + {{ break }} + {%- endif -%} + {%- endfor -%} jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}' selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}' @@ -326,10 +335,8 @@ trigger_variables: unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' trigger: - - platform: mqtt - topic: "{{jsontopic}}" - payload: "online" - value_template: "{{ value_json.event }}" + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" - platform: homeassistant event: start - platform: mqtt @@ -343,6 +350,10 @@ trigger: - platform: mqtt topic: "{{unselectedbgtopic}}" +condition: + - condition: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + action: - choose: ######################################################################### @@ -637,7 +648,12 @@ action: # Push configuration to device when it connects or Home Assistant starts - conditions: - condition: template - value_template: "{{ is_state(haspsensor, 'ON') and ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) or ((trigger.platform == 'mqtt') and (trigger.topic == jsontopic) and (trigger.payload_json.event == 'online'))}}" + value_template: >- + {{- + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + or + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) + -}} sequence: - service: mqtt.publish # send page button text data: diff --git a/Home_Assistant/blueprints/hasp_Create_Device_Triggers.yaml b/Home_Assistant/blueprints/hasp_Create_Device_Triggers.yaml index 09f5f38..c355661 100644 --- a/Home_Assistant/blueprints/hasp_Create_Device_Triggers.yaml +++ b/Home_Assistant/blueprints/hasp_Create_Device_Triggers.yaml @@ -24,7 +24,7 @@ blueprint: | Page 9 | Page 10 | Page 11 | |--------|---------|---------| - | ![Page 9](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p9_9buttons.png) | ![Page 10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p10_5buttons.png) | ![Page 11](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p11_1button.png) + | ![Page 9](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p9_9buttons.png) | ![Page 10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p10_5buttons.png) | ![Page 11](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p11_1button+1slider.png) @@ -63,7 +63,6 @@ variables: {{ break }} {%- endif -%} {%- endfor -%} - statetopic: '{{ "hasp/" ~ haspname ~ "/state" }}' haspsensor: >- {%- for entity in device_entities(haspdevice) -%} {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} @@ -78,13 +77,6 @@ variables: trigger_variables: haspdevice: !input haspdevice - haspname: >- - {%- for entity in device_entities(haspdevice) -%} - {%- if entity|regex_search("^sensor\.") -%} - {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} - {{ break }} - {%- endif -%} - {%- endfor -%} haspsensor: >- {%- for entity in device_entities(haspdevice) -%} {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} @@ -92,13 +84,10 @@ trigger_variables: {{ break }} {%- endif -%} {%- endfor -%} - jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' trigger: - - platform: mqtt - topic: "{{jsontopic}}" - payload: "online" - value_template: "{{ value_json.event }}" + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" - platform: homeassistant event: start diff --git a/Home_Assistant/blueprints/hasp_Display_Alarm_Control_page7.yaml b/Home_Assistant/blueprints/hasp_Display_Alarm_Control_page7.yaml index 0df7e48..a236b71 100644 --- a/Home_Assistant/blueprints/hasp_Display_Alarm_Control_page7.yaml +++ b/Home_Assistant/blueprints/hasp_Display_Alarm_Control_page7.yaml @@ -46,6 +46,7 @@ blueprint: min: 2 max: 10 mode: slider + unit_of_measurement: digits armservice: name: "Alarm arm service" description: 'Enter the alarm service call to issue when the ARM button is pressed. Typically this is one of "alarm_arm_away", "alarm_arm_home", "alarm_arm_night", or "alarm_arm_custom_bypass".' @@ -172,6 +173,8 @@ trigger: entity_id: !input alarmpanel - platform: homeassistant event: start + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" - platform: mqtt topic: "{{jsontopic}}" - platform: mqtt @@ -193,7 +196,14 @@ action: # RUN ACTIONS or Home Assistant Startup or HASP Connect - conditions: - condition: template - value_template: "{{ (trigger is not defined) or ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) or ((trigger.platform == 'mqtt') and (trigger.topic == jsontopic) and (trigger.payload_json.event == 'online'))}}" + value_template: >- + {{- + (trigger is not defined) + or + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + or + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) + -}} sequence: # Apply themes and set numbered button labels - service: mqtt.publish @@ -247,7 +257,8 @@ action: {"name":"{{haspname}} alarmcode {{repeat.index}}", "command_topic":"hasp/{{haspname}}/alarmcode/{{repeat.index}}", "availability":{"topic":"hasp/{{haspname}}/alwayson","payload_available":"ON"}, - "optimistic":"true", + "retain":true, + "optimistic":true, "icon":"mdi:bell-plus-outline", "unique_id":"{{haspClientId}}-alarmcode_{{repeat.index}}", "device":{ @@ -342,7 +353,7 @@ action: # Arm was pressed - conditions: - condition: template - value_template: '{{ (trigger.topic == jsontopic) and (trigger.payload_json.event == "p[7].b[15]") and (trigger.payload_json.value == "ON") and (alarmstate == "disarmed")}}' + value_template: '{{ (trigger.payload_json.event is defined) and (trigger.payload_json.event == "p[7].b[15]") and (trigger.payload_json.value == "ON") and (alarmstate == "disarmed")}}' sequence: - service_template: "{{armservice_name}}" data: @@ -367,7 +378,7 @@ action: # Disarm was pressed - conditions: - condition: template - value_template: '{{ (trigger.topic == jsontopic) and (trigger.payload_json.event == "p[7].b[15]") and (trigger.payload_json.value == "ON")}}' + value_template: '{{ (trigger.payload_json.event is defined) and (trigger.payload_json.event == "p[7].b[15]") and (trigger.payload_json.value == "ON")}}' sequence: - service: alarm_control_panel.alarm_disarm data: diff --git a/Home_Assistant/blueprints/hasp_Display_Calendar_with_Icon.yaml b/Home_Assistant/blueprints/hasp_Display_Calendar_with_Icon.yaml index 03a715b..1224213 100644 --- a/Home_Assistant/blueprints/hasp_Display_Calendar_with_Icon.yaml +++ b/Home_Assistant/blueprints/hasp_Display_Calendar_with_Icon.yaml @@ -40,6 +40,7 @@ blueprint: min: 1 max: 3 mode: slider + unit_of_measurement: page haspbutton: name: "HASP Button" description: "Select the HASP button (4-7) for the calendar. Refer to the HASP Page and Button reference above." @@ -49,6 +50,7 @@ blueprint: min: 4 max: 7 mode: slider + unit_of_measurement: button mode: parallel max_exceeded: silent @@ -169,6 +171,8 @@ trigger: at: "00:00:00" - platform: homeassistant event: start + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" - platform: mqtt topic: "{{jsontopic}}" - platform: mqtt @@ -195,9 +199,9 @@ action: {{- (trigger is not defined) or - ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) or - ((trigger.platform == 'mqtt') and (trigger.topic == jsontopic) and (trigger.payload_json.event == 'online')) + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) -}} sequence: - service: mqtt.publish diff --git a/Home_Assistant/blueprints/hasp_Display_Clock.yaml b/Home_Assistant/blueprints/hasp_Display_Clock.yaml index 5cfb904..3e19594 100644 --- a/Home_Assistant/blueprints/hasp_Display_Clock.yaml +++ b/Home_Assistant/blueprints/hasp_Display_Clock.yaml @@ -24,7 +24,7 @@ blueprint: | Page 9 | Page 10 | Page 11 | |--------|---------|---------| - | ![Page 9](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p9_9buttons.png) | ![Page 10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p10_5buttons.png) | ![Page 11](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p11_1button.png) + | ![Page 9](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p9_9buttons.png) | ![Page 10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p10_5buttons.png) | ![Page 11](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p11_1button+1slider.png) @@ -78,6 +78,7 @@ blueprint: min: 1 max: 11 mode: slider + unit_of_measurement: page haspbutton: name: "HASP Button" description: "Select the HASP button (4-15) for the clock. Refer to the HASP Page and Button reference above." @@ -87,6 +88,7 @@ blueprint: min: 4 max: 15 mode: slider + unit_of_measurement: button font_select: name: "Clock Font" description: "Select the font for the clock. Refer to the HASP Font reference above." @@ -261,10 +263,8 @@ trigger_variables: trigger: - platform: time_pattern seconds: 0 - - platform: mqtt - topic: "{{jsontopic}}" - payload: "online" - value_template: "{{ value_json.event }}" + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" - platform: homeassistant event: start - platform: mqtt @@ -276,7 +276,6 @@ trigger: - platform: mqtt topic: "{{unselectedbgtopic}}" - condition: - condition: template value_template: "{{ is_state(haspsensor, 'ON') }}" @@ -288,13 +287,13 @@ action: # Display clock and apply text style - conditions: - condition: template - value_template: >- + value_template: >- {{- (trigger is not defined) or - ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) or - ((trigger.platform == 'mqtt') and (trigger.topic == jsontopic) and (trigger.payload_json.event == 'online')) + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) -}} sequence: - service: mqtt.publish diff --git a/Home_Assistant/blueprints/hasp_Display_Clock_with_Icon.yaml b/Home_Assistant/blueprints/hasp_Display_Clock_with_Icon.yaml index b1b4dba..337ae8b 100644 --- a/Home_Assistant/blueprints/hasp_Display_Clock_with_Icon.yaml +++ b/Home_Assistant/blueprints/hasp_Display_Clock_with_Icon.yaml @@ -40,6 +40,7 @@ blueprint: min: 1 max: 3 mode: slider + unit_of_measurement: page haspbutton: name: "HASP Button" description: "Select the HASP button (4-7) for the clock. Refer to the HASP Page and Button reference above." @@ -49,6 +50,7 @@ blueprint: min: 4 max: 7 mode: slider + unit_of_measurement: button hour24: name: "24 hour clock display" default: false @@ -175,6 +177,8 @@ trigger: seconds: 0 - platform: homeassistant event: start + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" - platform: mqtt topic: "{{jsontopic}}" - platform: mqtt @@ -201,9 +205,9 @@ action: {{- (trigger is not defined) or - ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) or - ((trigger.platform == 'mqtt') and (trigger.topic == jsontopic) and (trigger.payload_json.event == 'online')) + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) -}} sequence: - service: mqtt.publish diff --git a/Home_Assistant/blueprints/hasp_Display_Dimmer_with_Icon.yaml b/Home_Assistant/blueprints/hasp_Display_Dimmer_with_Icon.yaml index cbc36b2..1ba669f 100644 --- a/Home_Assistant/blueprints/hasp_Display_Dimmer_with_Icon.yaml +++ b/Home_Assistant/blueprints/hasp_Display_Dimmer_with_Icon.yaml @@ -40,6 +40,7 @@ blueprint: min: 4 max: 5 mode: slider + unit_of_measurement: page haspbutton: name: "HASP Button" description: "Select the HASP button (7-9) for the dimmer. Refer to the HASP Page and Button reference above." @@ -49,6 +50,7 @@ blueprint: min: 7 max: 9 mode: slider + unit_of_measurement: button dimmer: name: "Light to control" description: "Select a light device which supports dimming" @@ -259,6 +261,8 @@ trigger_variables: trigger: - platform: state entity_id: !input dimmer + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" - platform: homeassistant event: start - platform: mqtt @@ -287,9 +291,9 @@ action: {{- (trigger is not defined) or - ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) or - ((trigger.platform == 'mqtt') and (trigger.topic == jsontopic) and (trigger.payload_json.event == 'online')) + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) -}} sequence: - service: mqtt.publish diff --git a/Home_Assistant/blueprints/hasp_Display_Entity_State_or_Attribute.yaml b/Home_Assistant/blueprints/hasp_Display_Entity_State_or_Attribute.yaml new file mode 100644 index 0000000..8b9a463 --- /dev/null +++ b/Home_Assistant/blueprints/hasp_Display_Entity_State_or_Attribute.yaml @@ -0,0 +1,425 @@ +blueprint: + name: "HASP p[x].b[y] displays the state or attribute value of an entity" + description: | + + # Description + + A HASP button displays the state or attribute value of an entity + + ![Preview](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/hasp_Display_Entity_State_or_Attribute.png) + + ## Examples + +
+ + ### Show current weather condition + + **Entity:** Select a weather provider of your choice + **Attribute:** `state` + **Title Case:** `true` + + ### Show current wind speed from Met.no + + **Entity:** The default Met.no provider from Home Assistant. If you left your location named "Home", the entity should be `weather.home` + **Attribute:** `wind_speed` + + ### Show current track name on a media player + + **Entity:** A media player with track information + **Attribute:** `media_title` + +
+ + ## HASP Page and Button Reference + + The images below show each available HASP page along with the layout of available button objects. + +
+ + | Page 0 | Pages 1-3 | Pages 4-5 | + |--------|-----------|-----------| + | ![Page 0](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p0_Init_Screen.png) | ![Pages 1-3](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p1-p3_4buttons.png) | ![Pages 4-5](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p4-p5_3sliders.png) | + + | Page 6 | Page 7 | Page 8 | + |--------|--------|--------| + | ![Page 6](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p6_8buttons.png) | ![Page 7](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p7_12buttons.png) | ![Page 8](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p8_5buttons+1slider.png) | + + | Page 9 | Page 10 | Page 11 | + |--------|---------|---------| + | ![Page 9](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p9_9buttons.png) | ![Page 10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p10_5buttons.png) | ![Page 11](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p11_1button+1slider.png) + +
+ + ## HASP Font Reference + +
+ + The Nextion display supports monospaced and proportional fonts. For monospace fonts, the HASP project includes [Consolas](https://docs.microsoft.com/en-us/typography/font-list/consolas) monospace in 4 sizes, [Webdings](https://en.wikipedia.org/wiki/Webdings#Character_set) in 1 size, and [Google's "Noto Sans"](https://github.com/googlefonts/noto-fonts) proportional in 5 sizes + + | Font | Name | Characters per line | Lines per button | + | :--- | :---------------- | :-------------------| :--------------- | + | 0 | Consolas 24 | 20 characters | 2 lines | + | 1 | Consolas 32 | 15 characters | 2 lines | + | 2 | Consolas 48 | 10 characters | 1 line | + | 3 | Consolas 80 | 6 characters | 1 line | + | 4 | Webdings 56 | 8 characters | 1 line | + | 5 | Noto Sans 24 | Proportional | 2 lines | + | 6 | Noto Sans 32 | Proportional | 2 lines | + | 7 | Noto Sans 48 | Proportional | 1 line | + | 8 | Noto Sans 64 | Proportional | 1 line | + | 9 | Noto Sans 80 | Proportional | 1 line | + | 10 | Noto Sans Bold 80 | Proportional | 1 line | + + ### Icons + + Fonts 5-10 also include [1400+ icons which you can copy and paste from here](https://htmlpreview.github.io/?https://github.com/aderusha/HASwitchPlate/blob/master/Documentation/Images/hasp-fontawesome5.html) + + ### Font examples + + ![HASP Fonts 0-3](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_0-3.png) ![HASP Fonts 4-7](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_4-7.png) ![HASP Fonts 8-10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_8-10.png) + +
+ + source_url: "https://github.com/HASwitchPlate/Blueprints/blob/main/hasp_Display_Entity_State_or_Attribute.yaml" + domain: automation + input: + haspdevice: + name: "HASP Device" + description: "Select the HASP device" + selector: + device: + integration: mqtt + manufacturer: "HASwitchPlate" + model: "HASPone v1.0.0" + hasppage: + name: "HASP Page" + description: "Select the HASP page (1-11). Refer to the HASP Page and Button reference above." + default: 1 + selector: + number: + min: 1 + max: 11 + mode: slider + unit_of_measurement: page + haspbutton: + name: "HASP Button" + description: "Select the HASP button (4-15) for the state display. Refer to the HASP Page and Button reference above." + default: 4 + selector: + number: + min: 4 + max: 15 + mode: slider + unit_of_measurement: button + selected_entity: + name: "Select an entity" + selector: + entity: + selected_attribute: + name: "Enter the desired entity attribute" + description: "Enter `state` to track the state of the sensor above, or enter an attribute name if the sensor has a specific attribute you want to track." + default: "state" + selector: + text: + prefix: + name: "State display prefix" + description: "Prefix for state display, leave blank for no prefix" + default: + selector: + text: + suffix: + name: "State display suffix" + description: "Suffix for state display, leave blank for no suffix" + default: + selector: + text: + font_select: + name: "Font" + description: "Select the font for the displayed text. Refer to the HASP Font Reference above." + default: "8 - Noto Sans 64" + selector: + select: + options: + - "0 - Consolas 24" + - "1 - Consolas 32" + - "2 - Consolas 48" + - "3 - Consolas 80" + - "4 - Webdings 56" + - "5 - Noto Sans 24" + - "6 - Noto Sans 32" + - "7 - Noto Sans 48" + - "8 - Noto Sans 64" + - "9 - Noto Sans 80" + - "10 - Noto Sans Bold 80" + xcen_select: + name: "Text horizontal alignment" + description: "Horizontal text alignment: 0=Left 1=Center 2=Right" + default: "1 - Centered" + selector: + select: + options: + - "0 - Left aligned" + - "1 - Centered" + - "2 - Right aligned" + ycen_select: + name: "Text vertical alignment" + description: "Vertical text alignment: 0=Top 1=Center 2=Bottom" + default: "1 - Centered" + selector: + select: + options: + - "0 - Top aligned" + - "1 - Centered" + - "2 - Bottom aligned" + wrap: + name: "Text wrap" + description: "Enable line-wrapping text if too long to fit in the button." + default: false + selector: + boolean: + title_case: + name: "Title Case" + description: "Apply The Title Case Filter To Capitalize The First Character Of Each Word In The Result" + default: false + selector: + boolean: + +mode: parallel +max_exceeded: silent + +variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + hasppage: !input hasppage + haspbutton: !input haspbutton + selected_entity: !input selected_entity + selected_attribute: !input selected_attribute + prefix: !input prefix + suffix: !input suffix + font_select: !input font_select + font: '{{ font_select.split(" - ")[0] | int }}' + xcen_select: !input xcen_select + xcen: '{{ xcen_select.split(" - ")[0] | int }}' + ycen_select: !input ycen_select + ycen: '{{ ycen_select.split(" - ")[0] | int }}' + wrap: !input wrap + title_case: !input title_case + haspobject: '{{ "p[" ~ hasppage ~ "].b[" ~ haspbutton ~ "]" }}' + commandtopic: '{{ "hasp/" ~ haspname ~ "/command/" ~ haspobject }}' + jsoncommandtopic: '{{ "hasp/" ~ haspname ~ "/command/json" }}' + selected_entity_attribute: "{{state_attr(selected_entity,selected_attribute)}}" + entity_text: >- + {%- if selected_attribute|lower == "state" -%} + {{- states(selected_entity) -}} + {%- else -%} + {{- state_attr(selected_entity, selected_attribute) -}} + {%- endif -%} + text: >- + {%- if prefix|lower != "none" -%} + {{ prefix }} + {%- endif -%} + {%- if title_case -%} + {{- entity_text | title -}} + {%- else -%} + {{ entity_text }} + {%- endif -%} + {%- if suffix|lower != "none" -%} + {{ suffix }} + {%- endif -%} + isbr: "{% if wrap == true %}1{% else %}0{% endif %}" + selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}' + selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + selectedfg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + selectedbg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + unselectedfg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + unselectedbg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + +trigger_variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + haspsensor: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} + {{ entity }} + {{ break }} + {%- endif -%} + {%- endfor -%} + jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' + selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}' + selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + +trigger: + - platform: state + entity_id: !input selected_entity + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + - platform: homeassistant + event: start + - platform: mqtt + topic: "{{jsontopic}}" + - platform: mqtt + topic: "{{selectedfgtopic}}" + - platform: mqtt + topic: "{{selectedbgtopic}}" + - platform: mqtt + topic: "{{unselectedfgtopic}}" + - platform: mqtt + topic: "{{unselectedbgtopic}}" + +condition: + - condition: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + +action: + - choose: + ######################################################################### + # RUN ACTIONS or Home Assistant Startup or HASP Connect + # Display attribute and apply text style + - conditions: + - condition: template + value_template: >- + {{- + (trigger is not defined) + or + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + or + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) + -}} + sequence: + - service: mqtt.publish + data: + topic: "{{jsoncommandtopic}}" + payload: >- + [ + "{{haspobject}}.font={{font}}", + "{{haspobject}}.xcen={{xcen}}", + "{{haspobject}}.ycen={{ycen}}", + "{{haspobject}}.isbr={{isbr}}", + "{{haspobject}}.pco={{selectedfg}}", + "{{haspobject}}.bco={{selectedbg}}", + "{{haspobject}}.pco2={{unselectedfg}}", + "{{haspobject}}.bco2={{unselectedbg}}", + "{{haspobject}}.txt=\"{{text}}\"" + ] + ######################################################################### + # Update display if our entity has changed state + - conditions: # Update display if our entity has changed state + - condition: template + value_template: '{{ (trigger.platform == "state") and (trigger.entity_id == selected_entity) }}' + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.txt" + payload: '"{{text}}"' + ######################################################################### + # Catch triggers fired by incoming MQTT messages + - conditions: + - condition: template + value_template: '{{ trigger.platform == "mqtt" }}' + sequence: + - choose: + ######################################################################### + # Theme: Apply selected foreground color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == selectedfgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.pco" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply selected background color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == selectedbgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.bco" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply unselected foreground color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedfgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.pco2" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply unselected background color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedbgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.bco2" + payload: "{{trigger.payload}}" + diff --git a/Home_Assistant/blueprints/hasp_Display_Media_Control_page8.yaml b/Home_Assistant/blueprints/hasp_Display_Media_Control_page8.yaml new file mode 100644 index 0000000..26eafe1 --- /dev/null +++ b/Home_Assistant/blueprints/hasp_Display_Media_Control_page8.yaml @@ -0,0 +1,353 @@ +blueprint: + name: "HASP p[8].b[all] Page 8 displays media controls" + description: | + + # Description + + Page 8 controls a selected media player with artist and track info, track back/play|pause/track forward, and volume control + + ![Preview](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/hasp_Display_Media_Control_page8.png) + + ## HASP Page and Button reference + +
+ + This automation is designed to work with the media controls found on page 8: + + | Page 8 | + |--------| + | ![Page 8](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p8_5buttons+1slider.png) | + + +
+ + source_url: "https://github.com/HASwitchPlate/Blueprints/blob/main/hasp_Display_Media_Control_page8.yaml" + domain: automation + input: + haspdevice: + name: "HASP Device" + description: "Select the HASP device" + selector: + device: + integration: mqtt + manufacturer: "HASwitchPlate" + model: "HASPone v1.0.0" + mediaplayer: + name: "Media Player to control" + description: "Select a media player to control" + selector: + entity: + domain: media_player + button4attribute: + name: "Top button attribute" + description: "Enter the media_player attribute to show on the top-most button on the media player screen." + default: "media_artist" + selector: + text: + button5attribute: + name: "Second button attribute" + description: "Select the media_player attribute to show on the second-from-top button on the media player screen." + default: "media_title" + selector: + text: + +mode: parallel +max_exceeded: silent + +variables: + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + haspsensor: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} + {{ entity }} + {{ break }} + {%- endif -%} + {%- endfor -%} + mediaplayer: !input mediaplayer + button4attribute: !input button4attribute + button5attribute: !input button5attribute + volumeobject: '{{ "p[8].b[9]" }}' + commandtopic: '{{ "hasp/" ~ haspname ~ "/command/" }}' + volumecommandtopic: '{{ "hasp/" ~ haspname ~ "/command/" ~ volumeobject ~ ".val" }}' + jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' + jsoncommandtopic: '{{ "hasp/" ~ haspname ~ "/command/json" }}' + selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}' + selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + selectedfg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + selectedbg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + unselectedfg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + unselectedbg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + + volume: "{% if state_attr(mediaplayer, 'volume_level')|lower == 'none' %}0{% else %}{{(state_attr(mediaplayer, 'volume_level')*255)|int}}{% endif %}" + button4text: "{% if state_attr(mediaplayer, button4attribute)|lower == 'none' %}{% else %}{{state_attr(mediaplayer, button4attribute)|wordwrap(19, wrapstring='\\\\r')}}{% endif %}" + # button4text: '{{state_attr(mediaplayer, button4attribute)|wordwrap(19, wrapstring="\\\\r")}}' + button4font: "{% set attr_length = button4text|safe|length%}{% if attr_length <= 6 -%}9{% elif attr_length <= 8 %}8{% elif attr_length <= 10 %}7{% else %}6{%- endif %}" + button5text: "{% if state_attr(mediaplayer, button5attribute)|lower == 'none' %}{% else %}{{state_attr(mediaplayer, button5attribute)|wordwrap(19, wrapstring='\\\\r')}}{% endif %}" + # button5text: '{{state_attr(mediaplayer, button5attribute)|wordwrap(19, wrapstring="\\\\r")}}' + button5font: "{% set attr_length = button5text|safe|length%}{% if attr_length <= 6 -%}9{% elif attr_length <= 8 %}8{% elif attr_length <= 10 %}7{% else %}6{%- endif %}" + button6text: "" # prev track + button6font: 8 + button7text: '{% if is_state(mediaplayer, "playing") %}{% else %}{% endif %}' + button7font: 8 + button8text: "" # next track + button8font: 8 + +trigger_variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + haspsensor: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} + {{ entity }} + {{ break }} + {%- endif -%} + {%- endfor -%} + jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' + selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}' + selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + +trigger: + - platform: state + entity_id: !input mediaplayer + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + - platform: homeassistant + event: start + - platform: mqtt + topic: "{{jsontopic}}" + - platform: mqtt + topic: "{{selectedfgtopic}}" + - platform: mqtt + topic: "{{selectedbgtopic}}" + - platform: mqtt + topic: "{{unselectedfgtopic}}" + - platform: mqtt + topic: "{{unselectedbgtopic}}" + +condition: + - condition: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + +action: + - choose: + ######################################################################### + # RUN ACTIONS or Home Assistant Startup or HASP Connect + # Apply styles and place text + - conditions: + - condition: template + value_template: >- + {{- + (trigger is not defined) + or + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + or + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) + -}} + sequence: + - service: mqtt.publish + data: + topic: "{{jsoncommandtopic}}" + payload: >- + ["p[8].b[4].pco={{selectedfg}}","p[8].b[4].bco={{selectedbg}}","p[8].b[4].pco2={{unselectedfg}}","p[8].b[4].bco2={{unselectedbg}}","p[8].b[4].font={{button4font}}","p[8].b[4].txt=\"{{button4text}}\"", + "p[8].b[5].pco={{selectedfg}}","p[8].b[5].bco={{selectedbg}}","p[8].b[5].pco2={{unselectedfg}}","p[8].b[5].bco2={{unselectedbg}}","p[8].b[5].font={{button5font}}","p[8].b[5].txt=\"{{button5text}}\"", + "p[8].b[6].pco={{selectedfg}}","p[8].b[6].bco={{selectedbg}}","p[8].b[6].pco2={{unselectedfg}}","p[8].b[6].bco2={{unselectedbg}}","p[8].b[6].font={{button6font}}","p[8].b[6].txt=\"{{button6text}}\"", + "p[8].b[7].pco={{selectedfg}}","p[8].b[7].bco={{selectedbg}}","p[8].b[7].pco2={{unselectedfg}}","p[8].b[7].bco2={{unselectedbg}}","p[8].b[7].font={{button7font}}","p[8].b[7].txt=\"{{button7text}}\"", + "p[8].b[8].pco={{selectedfg}}","p[8].b[8].bco={{selectedbg}}","p[8].b[8].pco2={{unselectedfg}}","p[8].b[8].bco2={{unselectedbg}}","p[8].b[8].font={{button8font}}","p[8].b[8].txt=\"{{button8text}}\"", + "{{volumeobject}}.pco={{unselectedfg}}","{{volumeobject}}.bco={{unselectedbg}}","{{volumeobject}}.val={{volume}}"] + + ######################################################################### + # Update volume if it has changed state + - conditions: # volume has changed value + - condition: template + value_template: '{{ (trigger.platform == "state") and (trigger.entity_id == mediaplayer) and (trigger.from_state.attributes.volume_level != trigger.to_state.attributes.volume_level)}}' + sequence: + - service: mqtt.publish + data: + topic: "{{volumecommandtopic}}" + payload: "{{volume}}" + ######################################################################### + # Update button4attribute and button5attribute + - conditions: + - condition: template + value_template: '{{ (trigger.platform == "state") and (trigger.entity_id == mediaplayer) }}' + sequence: + - service: mqtt.publish + data: + topic: "{{jsoncommandtopic}}" + payload: '["p[8].b[4].font={{button4font}}","p[8].b[4].txt=\"{{button4text}}\"","p[8].b[5].font={{button5font}}","p[8].b[5].txt=\"{{button5text}}\"","p[8].b[7].txt=\"{{button7text}}\""]' + + ######################################################################### + # Handle MQTT message triggers + - conditions: + - condition: template + value_template: '{{ trigger.platform == "mqtt" }}' + sequence: + - choose: + ######################################################################### + # Catch incoming JSON messages + - conditions: + - condition: template + value_template: "{{ (trigger.topic == jsontopic) and trigger.payload_json is defined }}" + sequence: + - choose: + ######################################################################### + # Set the volume value when the HASP slider has moved + - conditions: + - condition: template + value_template: '{{ (trigger.topic == jsontopic) and (trigger.payload_json.event == volumeobject ~ ".val") }}' + sequence: + - service: media_player.volume_set + entity_id: !input mediaplayer + data: + volume_level: "{{trigger.payload_json.value/255}}" + ######################################################################### + # Previous track button was pressed + - conditions: + - condition: template + value_template: '{{ (trigger.topic == jsontopic) and (trigger.payload_json.event == "p[8].b[6]") and (trigger.payload_json.value == "ON")}}' + sequence: + - service: media_player.media_previous_track + entity_id: !input mediaplayer + ######################################################################### + # Play/pause was pressed + - conditions: + - condition: template + value_template: '{{ (trigger.topic == jsontopic) and (trigger.payload_json.event == "p[8].b[7]") and (trigger.payload_json.value == "ON")}}' + sequence: + - service: media_player.media_play_pause + entity_id: !input mediaplayer + ######################################################################### + # Next track button was pressed + - conditions: + - condition: template + value_template: '{{ (trigger.topic == jsontopic) and (trigger.payload_json.event == "p[8].b[8]") and (trigger.payload_json.value == "ON")}}' + sequence: + - service: media_player.media_next_track + entity_id: !input mediaplayer + + ######################################################################### + # Theme: Apply selected foreground color when it changes. + - conditions: + - condition: template + value_template: "{{ trigger.topic == selectedfgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{jsoncommandtopic}}" + payload: >- + ["p[8].b[4].pco={{selectedfg}}", + "p[8].b[5].pco={{selectedfg}}", + "p[8].b[6].pco={{selectedfg}}", + "p[8].b[7].pco={{selectedfg}}", + "p[8].b[8].pco={{selectedfg}}"] + ######################################################################### + # Theme: Apply selected background color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == selectedbgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{jsoncommandtopic}}" + payload: >- + ["p[8].b[4].bco={{selectedbg}}", + "p[8].b[5].bco={{selectedbg}}", + "p[8].b[6].bco={{selectedbg}}", + "p[8].b[7].bco={{selectedbg}}", + "p[8].b[8].bco={{selectedbg}}"] + ######################################################################### + # Theme: Apply unselected foreground color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedfgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{jsoncommandtopic}}" + payload: >- + ["p[8].b[4].pco2={{unselectedfg}}", + "p[8].b[5].pco2={{unselectedfg}}", + "p[8].b[6].pco2={{unselectedfg}}", + "p[8].b[7].pco2={{unselectedfg}}", + "p[8].b[8].pco2={{unselectedfg}}", + "{{volumeobject}}.pco={{unselectedfg}}"] + ######################################################################### + # Theme: Apply unselected background color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedbgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{jsoncommandtopic}}" + payload: >- + ["p[8].b[4].bco2={{unselectedbg}}", + "p[8].b[5].bco2={{unselectedbg}}", + "p[8].b[6].bco2={{unselectedbg}}", + "p[8].b[7].bco2={{unselectedbg}}", + "p[8].b[8].bco2={{unselectedbg}}", + "{{volumeobject}}.bco={{unselectedbg}}"] diff --git a/Home_Assistant/blueprints/hasp_Display_Temperature_with_Icon_and_Colors.yaml b/Home_Assistant/blueprints/hasp_Display_Temperature_with_Icon_and_Colors.yaml index 773167f..3c187bc 100644 --- a/Home_Assistant/blueprints/hasp_Display_Temperature_with_Icon_and_Colors.yaml +++ b/Home_Assistant/blueprints/hasp_Display_Temperature_with_Icon_and_Colors.yaml @@ -61,6 +61,7 @@ blueprint: min: 1 max: 3 mode: slider + unit_of_measurement: page haspbutton: name: "HASP Button" description: "Select the HASP button (4-7) for the temperature. Refer to the HASP Page and Button reference above." @@ -70,6 +71,7 @@ blueprint: min: 4 max: 7 mode: slider + unit_of_measurement: button weather_provider: name: "Weather provider" description: "Select the weather provider to obtain the current outdoor temperature. If a temperature sensor is selected below, that will override this selection." @@ -86,7 +88,7 @@ blueprint: domain: sensor temperature_attribute: name: "Temperature sensor state or attribute to monitor" - description: 'Enter "state" to track the state of the sensor above, or enter an attribute name if the sensor has a specific attribute you want to track. Most uses will leave this set to "state".' + description: "Enter `state` to track the state of the sensor above, or enter an attribute name if the sensor has a specific attribute you want to track. Most uses will leave this set to `state`." default: "state" selector: text: @@ -227,7 +229,6 @@ variables: commandtopic: '{{ "hasp/" ~ haspname ~ "/command/" ~ haspobject }}' jsoncommandtopic: '{{ "hasp/" ~ haspname ~ "/command/json" }}' jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' - # temperature: '{{state_attr(weather_provider, "temperature")|int}}' temperature: >- {%- if temperature_sensor|lower == "none" -%} {{- state_attr(weather_provider, "temperature") -}} @@ -374,6 +375,8 @@ trigger_variables: trigger: - platform: state entity_id: !input weather_provider + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" - platform: homeassistant event: start - platform: mqtt @@ -402,9 +405,9 @@ action: {{- (trigger is not defined) or - ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) or - ((trigger.platform == 'mqtt') and (trigger.topic == jsontopic) and (trigger.payload_json.event == 'online')) + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) -}} sequence: - service: mqtt.publish diff --git a/Home_Assistant/blueprints/hasp_Display_Template.yaml b/Home_Assistant/blueprints/hasp_Display_Template.yaml new file mode 100644 index 0000000..ea7ab07 --- /dev/null +++ b/Home_Assistant/blueprints/hasp_Display_Template.yaml @@ -0,0 +1,396 @@ +blueprint: + name: "HASP p[x].b[y] displays the output of a template" + description: | + + # Description + + A button on the HASP will display the output of a template. The template is updated when the state of a selected entity updates. + + ![Preview](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/hasp_Display_Template.png) + + ## Examples + +
+ + ### Show tomorrow's high/low temperature from Met.no + + **Trigger entity:** The default Met.no provider from Home Assistant. If you left your location named "Home", the entity should be `weather.home` + **Template:** `Tomorrow\\rHigh: {{state_attr(trigger_entity, "forecast")[0].temperature|int}} Low: {{state_attr(trigger_entity, "forecast")[0].templow|int}}` + **Font:** `6` + +
+ + ## HASP Page and Button Reference + + The images below show each available HASP page along with the layout of available button objects. + +
+ + | Page 0 | Pages 1-3 | Pages 4-5 | + |--------|-----------|-----------| + | ![Page 0](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p0_Init_Screen.png) | ![Pages 1-3](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p1-p3_4buttons.png) | ![Pages 4-5](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p4-p5_3sliders.png) | + + | Page 6 | Page 7 | Page 8 | + |--------|--------|--------| + | ![Page 6](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p6_8buttons.png) | ![Page 7](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p7_12buttons.png) | ![Page 8](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p8_5buttons+1slider.png) | + + | Page 9 | Page 10 | Page 11 | + |--------|---------|---------| + | ![Page 9](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p9_9buttons.png) | ![Page 10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p10_5buttons.png) | ![Page 11](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p11_1button+1slider.png) + +
+ + ## HASP Font Reference + +
+ + The Nextion display supports monospaced and proportional fonts. For monospace fonts, the HASP project includes [Consolas](https://docs.microsoft.com/en-us/typography/font-list/consolas) monospace in 4 sizes, [Webdings](https://en.wikipedia.org/wiki/Webdings#Character_set) in 1 size, and [Google's "Noto Sans"](https://github.com/googlefonts/noto-fonts) proportional in 5 sizes + + | Font | Name | Characters per line | Lines per button | + | :--- | :---------------- | :-------------------| :--------------- | + | 0 | Consolas 24 | 20 characters | 2 lines | + | 1 | Consolas 32 | 15 characters | 2 lines | + | 2 | Consolas 48 | 10 characters | 1 line | + | 3 | Consolas 80 | 6 characters | 1 line | + | 4 | Webdings 56 | 8 characters | 1 line | + | 5 | Noto Sans 24 | Proportional | 2 lines | + | 6 | Noto Sans 32 | Proportional | 2 lines | + | 7 | Noto Sans 48 | Proportional | 1 line | + | 8 | Noto Sans 64 | Proportional | 1 line | + | 9 | Noto Sans 80 | Proportional | 1 line | + | 10 | Noto Sans Bold 80 | Proportional | 1 line | + + ### Icons + + Fonts 5-10 also include [1400+ icons which you can copy and paste from here](https://htmlpreview.github.io/?https://github.com/aderusha/HASwitchPlate/blob/master/Documentation/Images/hasp-fontawesome5.html) + + ### Font examples + + ![HASP Fonts 0-3](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_0-3.png) ![HASP Fonts 4-7](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_4-7.png) ![HASP Fonts 8-10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_8-10.png) + +
+ + source_url: "https://github.com/HASwitchPlate/Blueprints/blob/main/hasp_Display_Template.yaml" + domain: automation + input: + haspdevice: + name: "HASP Device" + description: "Select the HASP device" + selector: + device: + integration: mqtt + manufacturer: "HASwitchPlate" + model: "HASPone v1.0.0" + hasppage: + name: "HASP Page" + description: "Select the HASP page (1-11). Refer to the HASP Page and Button reference above." + default: 1 + selector: + number: + min: 1 + max: 11 + mode: slider + unit_of_measurement: page + haspbutton: + name: "HASP Button" + description: "Select the HASP button (4-15) for the template display. Refer to the HASP Page and Button reference above." + default: 4 + selector: + number: + min: 4 + max: 15 + mode: slider + unit_of_measurement: button + trigger_entity: + name: "Select an entity to trigger template update" + description: "Update the displayed template when the state or attributes of the selected entity update." + selector: + entity: + template: + name: "Template to output" + description: "Enter a well-formed [Home Assistant template](https://www.home-assistant.io/docs/configuration/templating/) string. The variable `trigger_entity` will contain the entity name selected above." + default: 'Forecast: {{state_attr("weather.home", "forecast")[0].condition|title}}' + selector: + text: + font_select: + name: "Font" + description: "Select the font for the displayed text. Refer to the HASP Font Reference above." + default: "8 - Noto Sans 64" + selector: + select: + options: + - "0 - Consolas 24" + - "1 - Consolas 32" + - "2 - Consolas 48" + - "3 - Consolas 80" + - "4 - Webdings 56" + - "5 - Noto Sans 24" + - "6 - Noto Sans 32" + - "7 - Noto Sans 48" + - "8 - Noto Sans 64" + - "9 - Noto Sans 80" + - "10 - Noto Sans Bold 80" + xcen_select: + name: "Text horizontal alignment" + description: "Horizontal text alignment: 0=Left 1=Center 2=Right" + default: "1 - Centered" + selector: + select: + options: + - "0 - Left aligned" + - "1 - Centered" + - "2 - Right aligned" + ycen_select: + name: "Text vertical alignment" + description: "Vertical text alignment: 0=Top 1=Center 2=Bottom" + default: "1 - Centered" + selector: + select: + options: + - "0 - Top aligned" + - "1 - Centered" + - "2 - Bottom aligned" + wrap: + name: "Text wrap" + description: "Enable line-wrapping text if too long to fit in the button." + default: false + selector: + boolean: + +mode: parallel +max_exceeded: silent + +variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + hasppage: !input hasppage + haspbutton: !input haspbutton + trigger_entity: !input trigger_entity + text: !input template + font_select: !input font_select + font: '{{ font_select.split(" - ")[0] | int }}' + xcen_select: !input xcen_select + xcen: '{{ xcen_select.split(" - ")[0] | int }}' + ycen_select: !input ycen_select + ycen: '{{ ycen_select.split(" - ")[0] | int }}' + wrap: !input wrap + haspobject: '{{ "p[" ~ hasppage ~ "].b[" ~ haspbutton ~ "]" }}' + commandtopic: '{{ "hasp/" ~ haspname ~ "/command/" ~ haspobject }}' + jsoncommandtopic: '{{ "hasp/" ~ haspname ~ "/command/json" }}' + isbr: "{% if wrap == true %}1{% else %}0{% endif %}" + selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}' + selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + selectedfg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + selectedbg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + unselectedfg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + unselectedbg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + +trigger_variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + haspsensor: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} + {{ entity }} + {{ break }} + {%- endif -%} + {%- endfor -%} + jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' + selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}' + selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + +trigger: + - platform: state + entity_id: !input trigger_entity + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + - platform: homeassistant + event: start + - platform: mqtt + topic: "{{jsontopic}}" + - platform: mqtt + topic: "{{selectedfgtopic}}" + - platform: mqtt + topic: "{{selectedbgtopic}}" + - platform: mqtt + topic: "{{unselectedfgtopic}}" + - platform: mqtt + topic: "{{unselectedbgtopic}}" + +condition: + - condition: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + +action: + - choose: + ######################################################################### + # RUN ACTIONS or Home Assistant Startup or HASP Connect + # Display template and apply text style + - conditions: + - condition: template + value_template: >- + {{- + (trigger is not defined) + or + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + or + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) + -}} + sequence: + - service: mqtt.publish + data: + topic: "{{jsoncommandtopic}}" + payload: >- + [ + "{{haspobject}}.font={{font}}", + "{{haspobject}}.xcen={{xcen}}", + "{{haspobject}}.ycen={{ycen}}", + "{{haspobject}}.isbr={{isbr}}", + "{{haspobject}}.pco={{selectedfg}}", + "{{haspobject}}.bco={{selectedbg}}", + "{{haspobject}}.pco2={{unselectedfg}}", + "{{haspobject}}.bco2={{unselectedbg}}", + "{{haspobject}}.txt=\"{{text}}\"" + ] + ######################################################################### + # Update display if our entity has changed state, or if the user presses the button + - conditions: + - condition: template + value_template: >- + {{- + ( + (trigger.platform == "state") + and + (trigger.entity_id == trigger_entity) + ) + or + ( + (trigger.topic == jsontopic) + and + (trigger.payload_json is defined) + and + (trigger.payload_json.event_type is defined) + and + (trigger.payload_json.event_type == "button_short_press") + and + (trigger.payload_json.event is defined) + and + (trigger.payload_json.event == haspobject) + ) + -}} + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.txt" + payload: '"{{text}}"' + ######################################################################### + # Catch triggers fired by incoming MQTT messages + - conditions: + - condition: template + value_template: '{{ trigger.platform == "mqtt" }}' + sequence: + - choose: + ######################################################################### + # Theme: Apply selected foreground color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == selectedfgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.pco" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply selected background color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == selectedbgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.bco" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply unselected foreground color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedfgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.pco2" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply unselected background color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedbgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.bco2" + payload: "{{trigger.payload}}" diff --git a/Home_Assistant/blueprints/hasp_Display_Text.yaml b/Home_Assistant/blueprints/hasp_Display_Text.yaml new file mode 100644 index 0000000..2d36458 --- /dev/null +++ b/Home_Assistant/blueprints/hasp_Display_Text.yaml @@ -0,0 +1,345 @@ +blueprint: + name: "HASP p[x].b[y] displays text" + description: | + + ## Description + + A button on the HASP will display text. This can be useful when combined with other blueprints which perform an action, but don't apply a label to a button. + Deploy both blueprints on the same button, and now you have a button that says things things and does things. + + ![Preview](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/hasp_Display_Text.png) + + ## HASP Page and Button Reference + + The images below show each available HASP page along with the layout of available button objects. + +
+ + | Page 0 | Pages 1-3 | Pages 4-5 | + |--------|-----------|-----------| + | ![Page 0](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p0_Init_Screen.png) | ![Pages 1-3](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p1-p3_4buttons.png) | ![Pages 4-5](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p4-p5_3sliders.png) | + + | Page 6 | Page 7 | Page 8 | + |--------|--------|--------| + | ![Page 6](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p6_8buttons.png) | ![Page 7](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p7_12buttons.png) | ![Page 8](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p8_5buttons+1slider.png) | + + | Page 9 | Page 10 | Page 11 | + |--------|---------|---------| + | ![Page 9](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p9_9buttons.png) | ![Page 10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p10_5buttons.png) | ![Page 11](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p11_1button+1slider.png) + +
+ + ## HASP Font Reference + +
+ + The Nextion display supports monospaced and proportional fonts. For monospace fonts, the HASP project includes [Consolas](https://docs.microsoft.com/en-us/typography/font-list/consolas) monospace in 4 sizes, [Webdings](https://en.wikipedia.org/wiki/Webdings#Character_set) in 1 size, and [Google's "Noto Sans"](https://github.com/googlefonts/noto-fonts) proportional in 5 sizes + + | Font | Name | Characters per line | Lines per button | + | :--- | :---------------- | :-------------------| :--------------- | + | 0 | Consolas 24 | 20 characters | 2 lines | + | 1 | Consolas 32 | 15 characters | 2 lines | + | 2 | Consolas 48 | 10 characters | 1 line | + | 3 | Consolas 80 | 6 characters | 1 line | + | 4 | Webdings 56 | 8 characters | 1 line | + | 5 | Noto Sans 24 | Proportional | 2 lines | + | 6 | Noto Sans 32 | Proportional | 2 lines | + | 7 | Noto Sans 48 | Proportional | 1 line | + | 8 | Noto Sans 64 | Proportional | 1 line | + | 9 | Noto Sans 80 | Proportional | 1 line | + | 10 | Noto Sans Bold 80 | Proportional | 1 line | + + ### Icons + + Fonts 5-10 also include [1400+ icons which you can copy and paste from here](https://htmlpreview.github.io/?https://github.com/aderusha/HASwitchPlate/blob/master/Documentation/Images/hasp-fontawesome5.html) + + ### Font examples + + ![HASP Fonts 0-3](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_0-3.png) ![HASP Fonts 4-7](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_4-7.png) ![HASP Fonts 8-10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_8-10.png) + +
+ + source_url: "https://github.com/HASwitchPlate/Blueprints/blob/main/hasp_Display_Text.yaml" + domain: automation + input: + haspdevice: + name: "HASP Device" + description: "Select the HASP device" + selector: + device: + integration: mqtt + manufacturer: "HASwitchPlate" + model: "HASPone v1.0.0" + hasppage: + name: "HASP Page" + description: "Select the HASP page (1-11). Refer to the HASP Page and Button reference above." + default: 1 + selector: + number: + min: 1 + max: 11 + mode: slider + unit_of_measurement: page + haspbutton: + name: "HASP Button" + description: "Select the HASP button (4-15) for the template display. Refer to the HASP Page and Button reference above." + default: 4 + selector: + number: + min: 4 + max: 15 + mode: slider + unit_of_measurement: button + text: + name: "Text to display" + description: "Enter text to be displayed on the HASP." + default: "Text to display" + selector: + text: + font_select: + name: "Font" + description: "Select the font for the displayed text. Refer to the HASP Font Reference above." + default: "8 - Noto Sans 64" + selector: + select: + options: + - "0 - Consolas 24" + - "1 - Consolas 32" + - "2 - Consolas 48" + - "3 - Consolas 80" + - "4 - Webdings 56" + - "5 - Noto Sans 24" + - "6 - Noto Sans 32" + - "7 - Noto Sans 48" + - "8 - Noto Sans 64" + - "9 - Noto Sans 80" + - "10 - Noto Sans Bold 80" + xcen_select: + name: "Text horizontal alignment" + description: "Horizontal text alignment: 0=Left 1=Center 2=Right" + default: "1 - Centered" + selector: + select: + options: + - "0 - Left aligned" + - "1 - Centered" + - "2 - Right aligned" + ycen_select: + name: "Text vertical alignment" + description: "Vertical text alignment: 0=Top 1=Center 2=Bottom" + default: "1 - Centered" + selector: + select: + options: + - "0 - Top aligned" + - "1 - Centered" + - "2 - Bottom aligned" + wrap: + name: "Text wrap" + description: "Enable line-wrapping text if too long to fit in the button." + default: false + selector: + boolean: + +mode: parallel +max_exceeded: silent + +variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + hasppage: !input hasppage + haspbutton: !input haspbutton + text: !input text + font_select: !input font_select + font: '{{ font_select.split(" - ")[0] | int }}' + xcen_select: !input xcen_select + xcen: '{{ xcen_select.split(" - ")[0] | int }}' + ycen_select: !input ycen_select + ycen: '{{ ycen_select.split(" - ")[0] | int }}' + wrap: !input wrap + haspobject: '{{ "p[" ~ hasppage ~ "].b[" ~ haspbutton ~ "]" }}' + commandtopic: '{{ "hasp/" ~ haspname ~ "/command/" ~ haspobject }}' + jsoncommandtopic: '{{ "hasp/" ~ haspname ~ "/command/json" }}' + isbr: "{% if wrap == true %}1{% else %}0{% endif %}" + selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}' + selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + selectedfg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + selectedbg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + unselectedfg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + unselectedbg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + +trigger_variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + haspsensor: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} + {{ entity }} + {{ break }} + {%- endif -%} + {%- endfor -%} + jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' + selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}' + selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + +trigger: + - platform: homeassistant + event: start + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + - platform: mqtt + topic: "{{selectedfgtopic}}" + - platform: mqtt + topic: "{{selectedbgtopic}}" + - platform: mqtt + topic: "{{unselectedfgtopic}}" + - platform: mqtt + topic: "{{unselectedbgtopic}}" + +condition: + - condition: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + +action: + - choose: + ######################################################################### + # RUN ACTIONS or Home Assistant Startup or HASP Connect + # Display text and apply text style + - conditions: + - condition: template + value_template: >- + {{- + (trigger is not defined) + or + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + or + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) + -}} + sequence: + - service: mqtt.publish + data: + topic: "{{jsoncommandtopic}}" + payload: >- + [ + "{{haspobject}}.font={{font}}", + "{{haspobject}}.xcen={{xcen}}", + "{{haspobject}}.ycen={{ycen}}", + "{{haspobject}}.isbr={{isbr}}", + "{{haspobject}}.pco={{selectedfg}}", + "{{haspobject}}.bco={{selectedbg}}", + "{{haspobject}}.pco2={{unselectedfg}}", + "{{haspobject}}.bco2={{unselectedbg}}", + "{{haspobject}}.txt=\"{{text}}\"" + ] + ######################################################################### + # Catch triggers fired by incoming MQTT messages + - conditions: + - condition: template + value_template: '{{ trigger.platform == "mqtt" }}' + sequence: + - choose: + ######################################################################### + # Theme: Apply selected foreground color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == selectedfgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.pco" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply selected background color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == selectedbgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.bco" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply unselected foreground color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedfgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.pco2" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply unselected background color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedbgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.bco2" + payload: "{{trigger.payload}}" + diff --git a/Home_Assistant/blueprints/hasp_Display_Toggle.yaml b/Home_Assistant/blueprints/hasp_Display_Toggle.yaml new file mode 100644 index 0000000..1ee58b5 --- /dev/null +++ b/Home_Assistant/blueprints/hasp_Display_Toggle.yaml @@ -0,0 +1,535 @@ +blueprint: + name: "HASP p[x].b[y] displays a toggle button" + description: | + + # Description + + Press a button on the HASP to toggle the state of an entity. The button colors will change in response to the on/off state or attribute of the selected entity. + + There are a lot of options below! No worries, the defaults should work in a lot of cases. + + ![Preview](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/hasp_Display_Toggle.gif) + + ## Examples + +
+ + ### Toggle play/pause on a media player + + **Entity to toggle:** A media player that supports play and pause commands + **Entity state to be considered "on":** `playing` + **Service call to turn "on":** `media_player.media_play` + **Service call to turn "off":** `media_player.media_pause` + **Text to display when entity is "on":** ' Pause' + **Text to display when entity is "off":** ' Play' + + ### Lock or unlock a door + + **Entity to toggle:** A lock that supports lock and unlock commands + **Entity state to be considered "on":** `locked` + **Service call to turn "on":** `lock.lock` + **Service call to turn "off":** `lock.unlock` + **Text to display when entity is "on":** ' Locked' + **Text to display when entity is "off":** ' Unlocked' + + ### Open or close a door + + **Entity to toggle:** A cover entity that supports open and close commands + **Entity state to be considered "on":** `closed` + **Service call to turn "on":** `cover.close_cover` + **Service call to turn "off":** `cover.open_cover` + **Text to display when entity is "on":** ' Closed' + **Text to display when entity is "off":** ' Open' + +
+ + ## HASP Page and Button Reference + + The images below show each available HASP page along with the layout of available button objects. + +
+ + | Page 0 | Pages 1-3 | Pages 4-5 | + |--------|-----------|-----------| + | ![Page 0](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p0_Init_Screen.png) | ![Pages 1-3](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p1-p3_4buttons.png) | ![Pages 4-5](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p4-p5_3sliders.png) | + + | Page 6 | Page 7 | Page 8 | + |--------|--------|--------| + | ![Page 6](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p6_8buttons.png) | ![Page 7](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p7_12buttons.png) | ![Page 8](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p8_5buttons+1slider.png) | + + | Page 9 | Page 10 | Page 11 | + |--------|---------|---------| + | ![Page 9](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p9_9buttons.png) | ![Page 10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p10_5buttons.png) | ![Page 11](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p11_1button+1slider.png) + +
+ + ## HASP Font Reference + +
+ + The Nextion display supports monospaced and proportional fonts. For monospace fonts, the HASP project includes [Consolas](https://docs.microsoft.com/en-us/typography/font-list/consolas) monospace in 4 sizes, [Webdings](https://en.wikipedia.org/wiki/Webdings#Character_set) in 1 size, and [Google's "Noto Sans"](https://github.com/googlefonts/noto-fonts) proportional in 5 sizes + + | Font | Name | Characters per line | Lines per button | + | :--- | :---------------- | :-------------------| :--------------- | + | 0 | Consolas 24 | 20 characters | 2 lines | + | 1 | Consolas 32 | 15 characters | 2 lines | + | 2 | Consolas 48 | 10 characters | 1 line | + | 3 | Consolas 80 | 6 characters | 1 line | + | 4 | Webdings 56 | 8 characters | 1 line | + | 5 | Noto Sans 24 | Proportional | 2 lines | + | 6 | Noto Sans 32 | Proportional | 2 lines | + | 7 | Noto Sans 48 | Proportional | 1 line | + | 8 | Noto Sans 64 | Proportional | 1 line | + | 9 | Noto Sans 80 | Proportional | 1 line | + | 10 | Noto Sans Bold 80 | Proportional | 1 line | + + ### Icons + + Fonts 5-10 also include [1400+ icons which you can copy and paste from here](https://htmlpreview.github.io/?https://github.com/aderusha/HASwitchPlate/blob/master/Documentation/Images/hasp-fontawesome5.html) + + ### Font examples + + ![HASP Fonts 0-3](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_0-3.png) ![HASP Fonts 4-7](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_4-7.png) ![HASP Fonts 8-10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_8-10.png) + +
+ + ## Nextion color codes + +
+ + The Nextion environment utilizes RGB 565 encoding. [Use this handy convertor](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to select your colors and convert to the RGB 565 format. + + Here are some example colors: + + | Color | Code | + |--------|-------| + | White | 65535 | + | Black | 0 | + | Grey | 25388 | + | Red | 63488 | + | Green | 2016 | + | Blue | 31 | + | Yellow | 65504 | + | Orange | 64512 | + | Brown | 48192 | + +
+ + source_url: "https://github.com/HASwitchPlate/Blueprints/blob/main/hasp_Display_Toggle.yaml" + domain: automation + input: + haspdevice: + name: "HASP Device" + description: "Select the HASP device" + selector: + device: + integration: mqtt + manufacturer: "HASwitchPlate" + model: "HASPone v1.0.0" + hasppage: + name: "HASP Page" + description: "Select the HASP page (1-11) for this toggle. Refer to the HASP Page and Button reference above." + default: 1 + selector: + number: + min: 1 + max: 11 + mode: slider + unit_of_measurement: page + haspbutton: + name: "HASP Button" + description: "Select the HASP button for this toggle. Refer to the HASP Page and Button reference above." + default: 4 + selector: + number: + min: 4 + max: 15 + mode: slider + unit_of_measurement: button + entity: + name: "Entity to toggle" + description: "Select an entity for this button to toggle" + selector: + entity: + attribute: + name: "Entity attribute or state to monitor" + description: 'Enter "state" to track the state of an entity, or enter an attribute name if the entity has a specific attribute you want to track. Most uses will leave this set to "state".' + default: "state" + selector: + text: + state_on: + name: 'Entity state to be considered "on"' + description: 'For most devices, this will be "on". If the selected entity state or attribute does not match this value (case insensitive), it will be considered "off"' + default: "on" + selector: + text: + action_on: + name: 'Action to turn "on"' + description: "Select an action that will turn the selected device on." + default: + selector: + action: + action_off: + name: 'Action to turn "off"' + description: "Select an action that will turn the selected device off" + default: + selector: + action: + text_on: + name: 'Text to display when entity is "on"' + description: 'Enter text to be displayed on the button when the selected entity is in the "on" state.' + default: "Entity on" + selector: + text: + text_off: + name: 'Text to display when entity is "off"' + description: 'Enter text to be displayed on the button when the selected entity is in the "off" state.' + default: "Entity off" + selector: + text: + on_fgcolor: + name: '"on" foreground color' + description: 'Text foreground color when the selected entity is "on" in Nextion RGB565 format (see "Nextion color codes" above for reference). -1 = Current theme selected foreground color.' + default: -1 + selector: + number: + min: -1 + max: 65535 + mode: slider + on_bgcolor: + name: '"on" background color' + description: 'Text background color when the selected entity is "on" in Nextion RGB565 format. -1 = Current theme selected background color.' + default: -1 + selector: + number: + min: -1 + max: 65535 + mode: slider + off_fgcolor: + name: '"off" foreground color' + description: 'Text foreground color when the selected entity is "off" in Nextion RGB565 format. -1 = Current theme unselected foreground color.' + default: -1 + selector: + number: + min: -1 + max: 65535 + mode: slider + off_bgcolor: + name: '"off" background color' + description: 'Text background color when the selected entity is "off" in Nextion RGB565 format. -1 = Current theme unselected background color.' + default: -1 + selector: + number: + min: -1 + max: 65535 + mode: slider + font_select: + name: "Font" + description: "Select the font for the displayed text. Refer to the HASP Font Reference above." + default: "8 - Noto Sans 64" + selector: + select: + options: + - "0 - Consolas 24" + - "1 - Consolas 32" + - "2 - Consolas 48" + - "3 - Consolas 80" + - "4 - Webdings 56" + - "5 - Noto Sans 24" + - "6 - Noto Sans 32" + - "7 - Noto Sans 48" + - "8 - Noto Sans 64" + - "9 - Noto Sans 80" + - "10 - Noto Sans Bold 80" + xcen_select: + name: "Text horizontal alignment" + description: "Horizontal text alignment: 0=Left 1=Center 2=Right" + default: "1 - Centered" + selector: + select: + options: + - "0 - Left aligned" + - "1 - Centered" + - "2 - Right aligned" + ycen_select: + name: "Text vertical alignment" + description: "Vertical text alignment: 0=Top 1=Center 2=Bottom" + default: "1 - Centered" + selector: + select: + options: + - "0 - Top aligned" + - "1 - Centered" + - "2 - Bottom aligned" + wrap: + name: "Text wrap" + description: "Enable line-wrapping text if too long to fit in the button." + default: false + selector: + boolean: + +mode: parallel +max_exceeded: silent + +variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + hasppage: !input hasppage + haspbutton: !input haspbutton + entity: !input entity + attribute: !input attribute + state_on: !input state_on + action_on: !input action_on + action_off: !input action_off + text_on: !input text_on + text_off: !input text_off + on_fgcolor: !input on_fgcolor + on_bgcolor: !input on_bgcolor + off_fgcolor: !input off_fgcolor + off_bgcolor: !input off_bgcolor + font_select: !input font_select + font: '{{ font_select.split(" - ")[0] | int }}' + xcen_select: !input xcen_select + xcen: '{{ xcen_select.split(" - ")[0] | int }}' + ycen_select: !input ycen_select + ycen: '{{ ycen_select.split(" - ")[0] | int }}' + wrap: !input wrap + haspobject: '{{ "p[" ~ hasppage ~ "].b[" ~ haspbutton ~ "]" }}' + commandtopic: '{{ "hasp/" ~ haspname ~ "/command/" ~ haspobject }}' + jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' + jsoncommandtopic: '{{ "hasp/" ~ haspname ~ "/command/json" }}' + isbr: "{% if wrap == true %}1{% else %}0{% endif %}" + selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}' + selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + selectedfg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + selectedbg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + unselectedfg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + unselectedbg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + entity_attribute: '{% if attribute|lower == "state" %}{{states(entity)}}{% else %}{{state_attr(entity,attribute)}}{% endif %}' + entity_state: "{% if entity_attribute|lower == state_on %}{{true}}{% else %}{{false}}{% endif %}" + toggle_selectedfg: "{% if entity_state %}{% if on_fgcolor|int >= 0 %}{{on_fgcolor}}{% else %}{{selectedfg}}{% endif %}{% else %}{% if off_fgcolor|int >= 0 %}{{off_fgcolor}}{% else %}{{unselectedfg}}{% endif %}{% endif %}" + toggle_selectedbg: "{% if entity_state %}{% if on_bgcolor|int >= 0 %}{{on_bgcolor}}{% else %}{{selectedbg}}{% endif %}{% else %}{% if off_bgcolor|int >= 0 %}{{off_bgcolor}}{% else %}{{unselectedbg}}{% endif %}{% endif %}" + toggle_unselectedfg: "{% if not entity_state %}{% if on_fgcolor|int >= 0 %}{{on_fgcolor}}{% else %}{{selectedfg}}{% endif %}{% else %}{% if off_fgcolor|int >= 0 %}{{off_fgcolor}}{% else %}{{unselectedfg}}{% endif %}{% endif %}" + toggle_unselectedbg: "{% if not entity_state %}{% if on_bgcolor|int >= 0 %}{{on_bgcolor}}{% else %}{{selectedbg}}{% endif %}{% else %}{% if off_bgcolor|int >= 0 %}{{off_bgcolor}}{% else %}{{unselectedbg}}{% endif %}{% endif %}" + text: "{% if entity_state %}{{text_on}}{% else %}{{text_off}}{% endif %}" + button_trigger: "ON" + +trigger_variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + haspsensor: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} + {{ entity }} + {{ break }} + {%- endif -%} + {%- endfor -%} + jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' + hasppage: !input hasppage + haspbutton: !input haspbutton + haspobject: '{{ "p[" ~ hasppage ~ "].b[" ~ haspbutton ~ "]" }}' + buttonjsonpayload: '{"event_type":"button_short_press","event":"{{haspobject}}","value":"ON"}' + selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}' + selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + +trigger: + - platform: state + entity_id: !input entity + - platform: homeassistant + event: start + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + - platform: mqtt + topic: "{{jsontopic}}" + payload: "{{buttonjsonpayload}}" + - platform: mqtt + topic: "{{selectedfgtopic}}" + - platform: mqtt + topic: "{{selectedbgtopic}}" + - platform: mqtt + topic: "{{unselectedfgtopic}}" + - platform: mqtt + topic: "{{unselectedbgtopic}}" + +condition: + - condition: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + +action: + - choose: + ######################################################################### + # Apply text and style when "RUN ACTIONS" is pressed by the user + - conditions: + - condition: template + value_template: >- + {{- + (trigger is not defined) + or + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + or + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) + -}} + sequence: + - service: mqtt.publish + data: + topic: "{{jsoncommandtopic}}" + payload: >- + [ + "{{haspobject}}.font={{font}}", + "{{haspobject}}.xcen={{xcen}}", + "{{haspobject}}.ycen={{ycen}}", + "{{haspobject}}.isbr={{isbr}}", + "{{haspobject}}.pco={{toggle_selectedfg}}", + "{{haspobject}}.bco={{toggle_selectedbg}}", + "{{haspobject}}.pco2={{toggle_unselectedfg}}", + "{{haspobject}}.bco2={{toggle_unselectedbg}}", + "{{haspobject}}.txt=\"{{text}}\"" + ] + + ######################################################################### + # Update display if our entity has changed state + - conditions: # Update display if our entity has changed state + - condition: template + value_template: '{{ (trigger.platform == "state") and (trigger.entity_id == entity) }}' + sequence: + - service: mqtt.publish + data: + topic: "{{jsoncommandtopic}}" + payload: >- + [ + "{{haspobject}}.pco={{toggle_selectedfg}}", + "{{haspobject}}.bco={{toggle_selectedbg}}", + "{{haspobject}}.pco2={{toggle_unselectedfg}}", + "{{haspobject}}.bco2={{toggle_unselectedbg}}", + "{{haspobject}}.txt=\"{{text}}\"" + ] + ######################################################################### + # Catch triggers fired by incoming MQTT messages + - conditions: + - condition: template + value_template: '{{ trigger.platform == "mqtt" }}' + sequence: + - choose: + ######################################################################### + # Catch incoming JSON messages + - conditions: + - condition: template + value_template: "{{ (trigger.topic == jsontopic) and trigger.payload_json is defined }}" + sequence: + - choose: + ######################################################################### + # Catch button, toggle entity OFF if currently ON + - conditions: + - condition: template + value_template: "{{ (trigger.topic == jsontopic) and (trigger.payload_json.event == haspobject) and (trigger.payload_json.value == button_trigger) and (entity_state)}}" + sequence: !input action_off + ######################################################################### + # Catch button, toggle entity ON if currently OFF + - conditions: + - condition: template + value_template: "{{ (trigger.topic == jsontopic) and (trigger.payload_json.event == haspobject) and (trigger.payload_json.value == button_trigger)}}" + sequence: !input action_on + ######################################################################### + # Theme: Apply selected foreground color when it changes + - conditions: + - condition: template + value_template: "{{ trigger.topic == selectedfgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.pco" + payload: "{{toggle_selectedfg}}" + ######################################################################### + # Theme: Apply selected background color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == selectedbgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.bco" + payload: "{{toggle_selectedbg}}" + ######################################################################### + # Theme: Apply unselected foreground color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedfgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.pco2" + payload: "{{toggle_unselectedfg}}" + ######################################################################### + # Theme: Apply unselected background color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedbgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.bco2" + payload: "{{toggle_unselectedbg}}" diff --git a/Home_Assistant/blueprints/hasp_Display_Volume_Control_page8.yaml b/Home_Assistant/blueprints/hasp_Display_Volume_Control_page8.yaml new file mode 100644 index 0000000..7c00e85 --- /dev/null +++ b/Home_Assistant/blueprints/hasp_Display_Volume_Control_page8.yaml @@ -0,0 +1,200 @@ +blueprint: + name: "HASP p[8].b[9] The slider button on page 8 displays a volume control" + description: | + + # Description + + The slider button on page 8 displays a volume control + + ![Preview](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/hasp_Display_Volume_Control_page8.png) + + ## HASP Page and Button reference + +
+ + This automation is designed to work with the silder found on page 8: + + | Page 8 | + |--------| + | ![Page 8](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p8_5buttons+1slider.png) | + + +
+ + source_url: "https://github.com/HASwitchPlate/Blueprints/blob/main/hasp_Display_Volume_Control_page8.yaml" + domain: automation + input: + haspdevice: + name: "HASP Device" + description: "Select the HASP device" + selector: + device: + integration: mqtt + manufacturer: "HASwitchPlate" + model: "HASPone v1.0.0" + volumeentity: + name: "Media Player to control" + description: "Select a media player to control volume" + selector: + entity: + domain: media_player + +mode: parallel +max_exceeded: silent + +variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + volumeentity: !input volumeentity + volumeobject: "p[8].b[9]" + commandtopic: '{{ "hasp/" ~ haspname ~ "/command/" }}' + volumecommandtopic: '{{ "hasp/" ~ haspname ~ "/command/" ~ volumeobject }}' + jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' + jsoncommandtopic: '{{ "hasp/" ~ haspname ~ "/command/json" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + unselectedfg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + unselectedbg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + volume: '{% if state_attr(volumeentity, "volume_level")|lower == "none" %}0{% else %}{{(state_attr(volumeentity, "volume_level")*255)|int}}{% endif %}' + +trigger_variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + haspsensor: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} + {{ entity }} + {{ break }} + {%- endif -%} + {%- endfor -%} + # jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' + volumetopic: '{{ "hasp/" ~ haspname ~ "/state/p[8].b[9].val" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + +trigger: + - platform: state + entity_id: !input volumeentity + - platform: homeassistant + event: start + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + - platform: mqtt + topic: "{{volumetopic}}" + - platform: mqtt + topic: "{{unselectedfgtopic}}" + - platform: mqtt + topic: "{{unselectedbgtopic}}" + +condition: + - condition: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + +action: + - choose: + ######################################################################### + # RUN ACTIONS or Home Assistant Startup or HASP Connect + # Apply text and style + - conditions: + - condition: template + value_template: >- + {{- + (trigger is not defined) + or + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + or + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) + -}} + sequence: + - service: mqtt.publish + data: + topic: "{{jsoncommandtopic}}" + payload: >- + ["{{volumeobject}}.pco={{unselectedfg}}", + "{{volumeobject}}.bco={{unselectedbg}}", + "{{volumeobject}}.val={{volume}}"] + + ######################################################################### + # Update display if our entity has changed state + - conditions: # volume has changed value, on/off state has also changed, and we're currently on the selected page + - condition: template + value_template: '{{ (trigger.platform == "state") and (trigger.entity_id == volumeentity) }}' + sequence: + - service: mqtt.publish + data: + topic: "{{volumecommandtopic}}.val" + payload: "{{volume}}" + + ######################################################################### + # Handle MQTT message triggers + - conditions: + - condition: template + value_template: '{{ trigger.platform == "mqtt" }}' + sequence: + - choose: + ######################################################################### + # Catch incoming volume slider change message + - conditions: + - condition: template + value_template: "{{ trigger.topic == volumetopic }}" + sequence: + - service: media_player.volume_set + entity_id: !input volumeentity + data: + volume_level: "{{ (trigger.payload | int) / 255 }}" + ######################################################################### + # Theme: Apply unselected foreground color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedfgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{volumecommandtopic}}.pco" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply unselected background color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedbgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{volumecommandtopic}}.bco" + payload: "{{trigger.payload}}" diff --git a/Home_Assistant/blueprints/hasp_Display_Weather_Condition.yaml b/Home_Assistant/blueprints/hasp_Display_Weather_Condition.yaml new file mode 100644 index 0000000..9cc394a --- /dev/null +++ b/Home_Assistant/blueprints/hasp_Display_Weather_Condition.yaml @@ -0,0 +1,360 @@ +blueprint: + name: "HASP p[x].b[y] displays the current weather condition" + description: | + + # Description + + A HASP button displays the current weather condition + + ![Preview](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/hasp_Display_Weather_Condition.png) + + ## HASP Page and Button Reference + + The images below show each available HASP page along with the layout of available button objects. + +
+ + | Page 0 | Pages 1-3 | Pages 4-5 | + |--------|-----------|-----------| + | ![Page 0](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p0_Init_Screen.png) | ![Pages 1-3](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p1-p3_4buttons.png) | ![Pages 4-5](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p4-p5_3sliders.png) | + + | Page 6 | Page 7 | Page 8 | + |--------|--------|--------| + | ![Page 6](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p6_8buttons.png) | ![Page 7](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p7_12buttons.png) | ![Page 8](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p8_5buttons+1slider.png) | + + | Page 9 | Page 10 | Page 11 | + |--------|---------|---------| + | ![Page 9](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p9_9buttons.png) | ![Page 10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p10_5buttons.png) | ![Page 11](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p11_1button+1slider.png) + +
+ + ## HASP Font Reference + +
+ + The Nextion display supports monospaced and proportional fonts. For monospace fonts, the HASP project includes [Consolas](https://docs.microsoft.com/en-us/typography/font-list/consolas) monospace in 4 sizes, [Webdings](https://en.wikipedia.org/wiki/Webdings#Character_set) in 1 size, and [Google's "Noto Sans"](https://github.com/googlefonts/noto-fonts) proportional in 5 sizes + + | Font | Name | Characters per line | Lines per button | + | :--- | :---------------- | :-------------------| :--------------- | + | 0 | Consolas 24 | 20 characters | 2 lines | + | 1 | Consolas 32 | 15 characters | 2 lines | + | 2 | Consolas 48 | 10 characters | 1 line | + | 3 | Consolas 80 | 6 characters | 1 line | + | 4 | Webdings 56 | 8 characters | 1 line | + | 5 | Noto Sans 24 | Proportional | 2 lines | + | 6 | Noto Sans 32 | Proportional | 2 lines | + | 7 | Noto Sans 48 | Proportional | 1 line | + | 8 | Noto Sans 64 | Proportional | 1 line | + | 9 | Noto Sans 80 | Proportional | 1 line | + | 10 | Noto Sans Bold 80 | Proportional | 1 line | + + ### Icons + + Fonts 5-10 also include [1400+ icons which you can copy and paste from here](https://htmlpreview.github.io/?https://github.com/aderusha/HASwitchPlate/blob/master/Documentation/Images/hasp-fontawesome5.html) + + ### Font examples + + ![HASP Fonts 0-3](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_0-3.png) ![HASP Fonts 4-7](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_4-7.png) ![HASP Fonts 8-10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_8-10.png) + +
+ + source_url: "https://github.com/HASwitchPlate/Blueprints/blob/main/hasp_Display_Weather_Condition.yaml" + domain: automation + input: + haspdevice: + name: "HASP Device" + description: "Select the HASP device" + selector: + device: + integration: mqtt + manufacturer: "HASwitchPlate" + model: "HASPone v1.0.0" + hasppage: + name: "HASP Page" + description: "Select the HASP page (1-11) for the weather condition. Refer to the HASP Page and Button reference above." + default: 1 + selector: + number: + min: 1 + max: 11 + mode: slider + unit_of_measurement: page + haspbutton: + name: "HASP Button" + description: "Select the HASP button (4-15) for the weather condition. Refer to the HASP Page and Button reference above." + default: 4 + selector: + number: + min: 4 + max: 15 + mode: slider + unit_of_measurement: button + weather_provider: + name: "Weather provider" + description: "Select the weather provider to obtain the weather condition" + selector: + entity: + domain: weather + font_select: + name: "Font" + description: "Select the font for the displayed text. Refer to the HASP Font Reference above." + default: "8 - Noto Sans 64" + selector: + select: + options: + - "0 - Consolas 24" + - "1 - Consolas 32" + - "2 - Consolas 48" + - "3 - Consolas 80" + - "4 - Webdings 56" + - "5 - Noto Sans 24" + - "6 - Noto Sans 32" + - "7 - Noto Sans 48" + - "8 - Noto Sans 64" + - "9 - Noto Sans 80" + - "10 - Noto Sans Bold 80" + xcen_select: + name: "Text horizontal alignment" + description: "Horizontal text alignment: 0=Left 1=Center 2=Right" + default: "1 - Centered" + selector: + select: + options: + - "0 - Left aligned" + - "1 - Centered" + - "2 - Right aligned" + ycen_select: + name: "Text vertical alignment" + description: "Vertical text alignment: 0=Top 1=Center 2=Bottom" + default: "1 - Centered" + selector: + select: + options: + - "0 - Top aligned" + - "1 - Centered" + - "2 - Bottom aligned" + wrap: + name: "Text wrap" + description: "Enable line-wrapping text if too long to fit in the button." + default: false + selector: + boolean: + +mode: parallel +max_exceeded: silent + +variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + hasppage: !input hasppage + haspbutton: !input haspbutton + weather_provider: !input weather_provider + font_select: !input font_select + font: '{{ font_select.split(" - ")[0] | int }}' + xcen_select: !input xcen_select + xcen: '{{ xcen_select.split(" - ")[0] | int }}' + ycen_select: !input ycen_select + ycen: '{{ ycen_select.split(" - ")[0] | int }}' + wrap: !input wrap + haspobject: '{{ "p[" ~ hasppage ~ "].b[" ~ haspbutton ~ "]" }}' + commandtopic: '{{ "hasp/" ~ haspname ~ "/command/" ~ haspobject }}' + jsoncommandtopic: '{{ "hasp/" ~ haspname ~ "/command/json" }}' + jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' + text: '{{states(weather_provider)|replace("windy-variant","windy")|replace("clear-night","clear night")|replace("partlycloudy","partly cloudy")|replace("lightning-rainy","lightning & rain")|replace("snowy-rainy","snow & rain")|title}}' + isbr: "{% if wrap == true %}1{% else %}0{% endif %}" + selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}' + selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + selectedfg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + selectedbg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + unselectedfg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + unselectedbg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + +trigger_variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + haspsensor: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} + {{ entity }} + {{ break }} + {%- endif -%} + {%- endfor -%} + selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}' + selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + +trigger: + - platform: state + entity_id: !input weather_provider + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + - platform: homeassistant + event: start + - platform: mqtt + topic: "{{selectedfgtopic}}" + - platform: mqtt + topic: "{{selectedbgtopic}}" + - platform: mqtt + topic: "{{unselectedfgtopic}}" + - platform: mqtt + topic: "{{unselectedbgtopic}}" + +condition: + - condition: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + +action: + - choose: + ######################################################################### + # RUN ACTIONS or Home Assistant Startup or HASP Connect + # Display weather condition and apply text style + - conditions: + - condition: template + value_template: >- + {{- + (trigger is not defined) + or + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + or + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) + -}} + sequence: + - service: mqtt.publish + data: + topic: "{{jsoncommandtopic}}" + payload: >- + [ + "{{haspobject}}.font={{font}}", + "{{haspobject}}.xcen={{xcen}}", + "{{haspobject}}.ycen={{ycen}}", + "{{haspobject}}.isbr={{isbr}}", + "{{haspobject}}.pco={{selectedfg}}", + "{{haspobject}}.bco={{selectedbg}}", + "{{haspobject}}.pco2={{unselectedfg}}", + "{{haspobject}}.bco2={{unselectedbg}}", + "{{haspobject}}.txt=\"{{text}}\"" + ] + + ######################################################################### + # Update text if our weather provider changed state + - conditions: + - condition: template + value_template: '{{ (trigger.platform == "state") and (trigger.entity_id == weather_provider) and (trigger.from_state.state != trigger.to_state.state) }}' + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.txt" + payload: '\"{{text}}\"' + + ######################################################################### + # Handle MQTT message triggers + - conditions: + - condition: template + value_template: '{{ trigger.platform == "mqtt" }}' + sequence: + - choose: + ######################################################################### + # Theme: Apply selected foreground color when it changes. + # If the page is currently active, delay a moment before applying the overlay + # so it will fire after any other theme elements being applied. + - conditions: + - condition: template + value_template: "{{ trigger.topic == selectedfgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.pco" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply selected background color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == selectedbgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.bco" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply unselected foreground color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedfgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.pco2" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply unselected background color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedbgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.bco2" + payload: "{{trigger.payload}}" diff --git a/Home_Assistant/blueprints/hasp_Display_Weather_Condition_with_Icon.yaml b/Home_Assistant/blueprints/hasp_Display_Weather_Condition_with_Icon.yaml index 08a9648..5f64252 100644 --- a/Home_Assistant/blueprints/hasp_Display_Weather_Condition_with_Icon.yaml +++ b/Home_Assistant/blueprints/hasp_Display_Weather_Condition_with_Icon.yaml @@ -39,6 +39,7 @@ blueprint: min: 1 max: 3 mode: slider + unit_of_measurement: page haspbutton: name: "HASP Button" description: "Select the HASP button (4-7) for the temperature. Refer to the object map in the HASP documentation." @@ -48,6 +49,7 @@ blueprint: min: 4 max: 7 mode: slider + unit_of_measurement: button weather_provider: name: "Weather provider" description: "Select the weather provider to obtain the temperature" @@ -125,7 +127,15 @@ variables: replace("snowy-rainy","snow & rain") | title -}} - font: '{%set weatherlength=states(weather_provider)|length %}{% if weatherlength < 7 -%}8{% elif weatherlength < 12 %}7{% else %}6{%- endif %}' + font: >- + {%- set weatherlength = text | length -%} + {%- if weatherlength < 7 -%} + 8 + {%- elif weatherlength < 12 -%} + 7 + {%- else -%} + 6 + {%- endif -%} ypos: "{{(haspbutton|int - 4) * 67 + 2}}" xpos: 0 iconwidth: 65 @@ -226,6 +236,8 @@ trigger: entity_id: !input weather_provider - platform: homeassistant event: start + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" - platform: mqtt topic: "{{jsontopic}}" - platform: mqtt @@ -252,11 +264,15 @@ action: {{- (trigger is not defined) or - ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) or - ((trigger.platform == 'mqtt') and (trigger.topic == jsontopic) and (trigger.payload_json.event == 'online')) + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) -}} sequence: + - service: mqtt.publish + data: + topic: "debug" + payload: "weather condition text: {{text}} states(weather_provider): {{states(weather_provider)}}" - service: mqtt.publish data: topic: "{{jsoncommandtopic}}" diff --git a/Home_Assistant/blueprints/hasp_Display_Weather_Forecast.yaml b/Home_Assistant/blueprints/hasp_Display_Weather_Forecast.yaml new file mode 100644 index 0000000..c11a6a6 --- /dev/null +++ b/Home_Assistant/blueprints/hasp_Display_Weather_Forecast.yaml @@ -0,0 +1,394 @@ +blueprint: + name: "HASP p[x].b[y] displays the weather forecast" + description: | + + ## Description + + A HASP button displays an attribute of a selected weather forecast. You can use this to display tomorrow's condition, or tonight's low temp. + Available forecast conditions will vary by weather provider, check your selected provider's state under `Developer Tools` > `States` to get + a sense of what your selected provider has to offer. + + ![Preview](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/hasp_Display_Weather_Forecast.png) + + ### HASP Page and Button reference + +
+ + | Page 0 | Pages 1-3 | Pages 4-5 | + |--------|-----------|-----------| + | ![Page 0](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p0_Init_Screen.png) | ![Pages 1-3](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p1-p3_4buttons.png) | ![Pages 4-5](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p4-p5_3sliders.png) | + + | Page 6 | Page 7 | Page 8 | + |--------|--------|--------| + | ![Page 6](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p6_8buttons.png) | ![Page 7](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p7_12buttons.png) | ![Page 8](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p8_5buttons+1slider.png) | + + | Page 9 | Page 10 | Page 11 | + |--------|---------|---------| + | ![Page 9](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p9_9buttons.png) | ![Page 10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p10_5buttons.png) | ![Page 11](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p11_1button+1slider.png) + +
+ + ## HASP Font reference + +
+ + The Nextion display supports monospaced and proportional fonts. For monospace fonts, the HASP project includes [Consolas](https://docs.microsoft.com/en-us/typography/font-list/consolas) in 4 sizes and [Webdings](https://en.wikipedia.org/wiki/Webdings#Character_set) in 1 size. + + | Number | Font | Characters per line | Lines per button | + |--------|-------------------|---------------------|------------------| + | 0 | Consolas 24 point | 20 characters | 2 lines | + | 1 | Consolas 32 point | 15 characters | 2 lines | + | 2 | Consolas 48 point | 10 characters | 1 lines | + | 3 | Consolas 80 point | 6 characters | 1 lines | + | 4 | Webdings 56 point | 8 characters | 1 lines | + + The HASP also includes [Google's "Noto Sans"](https://github.com/googlefonts/noto-fonts) proportional font in 5 sizes. + + | Number | Font | + |--------|----------------------------| + | 5 | Noto Sans Regular 24 point | + | 6 | Noto Sans Regular 32 point | + | 7 | Noto Sans Regular 48 point | + | 8 | Noto Sans Regular 64 point | + | 9 | Noto Sans Regular 80 point | + | 10 | Noto Sans Bold 80 point | + + ### Font examples + + ![HASP Fonts 0-3](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_0-3.png) ![HASP Fonts 4-7](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_4-7.png) ![HASP Fonts 8-10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_Fonts_8-10.png) + +
+ source_url: "https://github.com/HASwitchPlate/Blueprints/blob/main/hasp_Display_Weather_Forecast.yaml" + domain: automation + input: + haspdevice: + name: "HASP Device" + description: "Select the HASP device" + selector: + device: + integration: mqtt + manufacturer: "HASwitchPlate" + model: "HASPone v1.0.0" + hasppage: + name: "HASP Page" + description: "Select the HASP page (1-11) for the forecast. Refer to the HASP Page and Button reference above." + default: 1 + selector: + number: + min: 1 + max: 11 + mode: slider + unit_of_measurement: page + haspbutton: + name: "HASP Button" + description: "Select the HASP button (4-15) for the forecast. Refer to the HASP Page and Button reference above." + default: 4 + selector: + number: + min: 4 + max: 15 + mode: slider + unit_of_measurement: button + weather_provider: + name: "Weather provider" + description: "Select the weather provider to obtain the forecast" + selector: + entity: + domain: weather + forecast_index: + name: "Forecast index" + description: 'Weather forecasts are provided at intervals determined by your weather source. The next time interval will be index "0". Increment this number for future forecasts' + default: 0 + selector: + number: + min: 0 + max: 10 + mode: slider + unit_of_measurement: index + forecast_attribute: + name: "Enter the desired forecast attribute" + description: 'Type in the name of the desired forecast attribute for your provider. "condition" is a common attribute for many providers.' + default: "condition" + selector: + text: + prefix: + name: "Forecast display prefix" + description: 'Prefix for forecast display, maybe something like "tonight: " or "tomorrow: ". Leave blank for no prefix. Use "\\r" for a newline.' + default: + selector: + text: + font_select: + name: "Font" + description: "Select the font for the displayed text. Refer to the HASP Font Reference above." + default: "8 - Noto Sans 64" + selector: + select: + options: + - "0 - Consolas 24" + - "1 - Consolas 32" + - "2 - Consolas 48" + - "3 - Consolas 80" + - "4 - Webdings 56" + - "5 - Noto Sans 24" + - "6 - Noto Sans 32" + - "7 - Noto Sans 48" + - "8 - Noto Sans 64" + - "9 - Noto Sans 80" + - "10 - Noto Sans Bold 80" + xcen_select: + name: "Text horizontal alignment" + description: "Horizontal text alignment: 0=Left 1=Center 2=Right" + default: "1 - Centered" + selector: + select: + options: + - "0 - Left aligned" + - "1 - Centered" + - "2 - Right aligned" + ycen_select: + name: "Text vertical alignment" + description: "Vertical text alignment: 0=Top 1=Center 2=Bottom" + default: "1 - Centered" + selector: + select: + options: + - "0 - Top aligned" + - "1 - Centered" + - "2 - Bottom aligned" + wrap: + name: "Text wrap" + default: false + description: "Enable line-wrapping text if too long to fit in the button." + selector: + boolean: + title_case: + name: "Title Case" + description: "Apply The Title Case Filter To Capitalize The First Character Of Each Word In The Result" + default: true + selector: + boolean: + +mode: parallel +max_exceeded: silent + +variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + hasppage: !input hasppage + haspbutton: !input haspbutton + weather_provider: !input weather_provider + forecast_index: !input forecast_index + forecast_attribute: !input forecast_attribute + prefix: !input prefix + font_select: !input font_select + font: '{{ font_select.split(" - ")[0] | int }}' + xcen_select: !input xcen_select + xcen: '{{ xcen_select.split(" - ")[0] | int }}' + ycen_select: !input ycen_select + ycen: '{{ ycen_select.split(" - ")[0] | int }}' + wrap: !input wrap + title_case: !input title_case + haspobject: '{{ "p[" ~ hasppage ~ "].b[" ~ haspbutton ~ "]" }}' + commandtopic: '{{ "hasp/" ~ haspname ~ "/command/" ~ haspobject }}' + jsoncommandtopic: '{{ "hasp/" ~ haspname ~ "/command/json" }}' + text: >- + {%- if prefix|lower != "none" -%} + {{ prefix }} + {%- endif -%} + {%- if title_case -%} + {{ state_attr(weather_provider, "forecast")[forecast_index|int].get(forecast_attribute) | title }} + {%- else -%} + {{ state_attr(weather_provider, "forecast")[forecast_index|int].get(forecast_attribute) }} + {%- endif -%} + isbr: "{% if wrap == true %}1{% else %}0{% endif %}" + selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}' + selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + selectedfg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + selectedbg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + unselectedfg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + unselectedbg: >- + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {{ break }} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + +trigger_variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + haspsensor: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} + {{ entity }} + {{ break }} + {%- endif -%} + {%- endfor -%} + selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}' + selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}' + unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}' + unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}' + +trigger: + - platform: state + entity_id: !input weather_provider + - platform: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + - platform: homeassistant + event: start + - platform: mqtt + topic: "{{selectedfgtopic}}" + - platform: mqtt + topic: "{{selectedbgtopic}}" + - platform: mqtt + topic: "{{unselectedfgtopic}}" + - platform: mqtt + topic: "{{unselectedbgtopic}}" + +condition: + - condition: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + +action: + - choose: + ######################################################################### + # Display attribute and apply text style when "RUN ACTIONS" is pressed by the user + - conditions: + - condition: template + value_template: >- + {{- + (trigger is not defined) + or + ((trigger.platform == 'homeassistant') and (trigger.event == 'start')) + or + ((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON')) + -}} + sequence: + - service: mqtt.publish + data: + topic: "{{jsoncommandtopic}}" + payload: >- + [ + "{{haspobject}}.font={{font}}", + "{{haspobject}}.xcen={{xcen}}", + "{{haspobject}}.ycen={{ycen}}", + "{{haspobject}}.isbr={{isbr}}", + "{{haspobject}}.pco={{selectedfg}}", + "{{haspobject}}.bco={{selectedbg}}", + "{{haspobject}}.pco2={{unselectedfg}}", + "{{haspobject}}.bco2={{unselectedbg}}", + "{{haspobject}}.txt=\"{{text}}\"" + ] + ######################################################################### + # Update forecast if our weather provider changed state + - conditions: + - condition: template + value_template: '{{ (trigger.platform == "state") and (trigger.entity_id == weather_provider) }}' + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.txt" + payload: '"{{text}}"' + ######################################################################### + # Catch triggers fired by incoming MQTT messages + - conditions: + - condition: template + value_template: '{{ trigger.platform == "mqtt" }}' + sequence: + - choose: + ######################################################################### + # Theme: Apply selected foreground color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == selectedfgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.pco" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply selected background color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == selectedbgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.bco" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply unselected foreground color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedfgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.pco2" + payload: "{{trigger.payload}}" + ######################################################################### + # Theme: Apply unselected background color on change + - conditions: + - condition: template + value_template: "{{ trigger.topic == unselectedbgtopic }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.bco2" + payload: "{{trigger.payload}}" diff --git a/Home_Assistant/blueprints/hasp_Perform_Action.yaml b/Home_Assistant/blueprints/hasp_Perform_Action.yaml new file mode 100644 index 0000000..bb7bc4f --- /dev/null +++ b/Home_Assistant/blueprints/hasp_Perform_Action.yaml @@ -0,0 +1,111 @@ +blueprint: + name: "HASP p[x].b[y] performs an action when pressed" + description: | + + # Description + + A button on the HASP will perform an action when pressed. Can be combined on a button with another blueprint which displays text. + + ### HASP Page and Button reference + +
+ + | Page 0 | Pages 1-3 | Pages 4-5 | + |--------|-----------|-----------| + | ![Page 0](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p0_Init_Screen.png) | ![Pages 1-3](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p1-p3_4buttons.png) | ![Pages 4-5](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p4-p5_3sliders.png) | + + | Page 6 | Page 7 | Page 8 | + |--------|--------|--------| + | ![Page 6](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p6_8buttons.png) | ![Page 7](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p7_12buttons.png) | ![Page 8](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p8_5buttons+1slider.png) | + + | Page 9 | Page 10 | Page 11 | + |--------|---------|---------| + | ![Page 9](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p9_9buttons.png) | ![Page 10](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p10_5buttons.png) | ![Page 11](https://raw.githubusercontent.com/HASwitchPlate/Blueprints/main/images/NextionUI_p11_1button+1slider.png) + +
+ + source_url: "https://github.com/HASwitchPlate/Blueprints/blob/main/hasp_Perform_Action.yaml" + domain: automation + input: + haspdevice: + name: "HASP Device" + description: "Select the HASP device" + selector: + device: + integration: mqtt + manufacturer: "HASwitchPlate" + model: "HASPone v1.0.0" + hasppage: + name: "HASP Page" + description: "Select the HASP page (1-11) for this automation. Refer to the HASP Page and Button reference above." + default: 1 + selector: + number: + min: 1 + max: 11 + mode: slider + unit_of_measurement: page + haspbutton: + name: "HASP Button" + description: "Select the HASP button for this automation. Refer to the HASP Page and Button reference above." + default: 4 + selector: + number: + min: 4 + max: 15 + mode: slider + unit_of_measurement: button + selected_action: + name: "Action to perform" + description: "Select an action to be performed when this button is pressed." + default: + selector: + action: + +mode: parallel +max_exceeded: silent + +variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + hasppage: !input hasppage + haspbutton: !input haspbutton + +trigger_variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\.") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {{ break }} + {%- endif -%} + {%- endfor -%} + haspsensor: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} + {{ entity }} + {{ break }} + {%- endif -%} + {%- endfor -%} + jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}' + hasppage: !input hasppage + haspbutton: !input haspbutton + haspobject: '{{ "p[" ~ hasppage ~ "].b[" ~ haspbutton ~ "]" }}' + buttonjsonpayload: '{"event_type":"button_short_press","event":"{{haspobject}}","value":"ON"}' + +trigger: + - platform: mqtt + topic: "{{jsontopic}}" + payload: "{{buttonjsonpayload}}" + +condition: + - condition: template + value_template: "{{ is_state(haspsensor, 'ON') }}" + +action: !input selected_action diff --git a/LICENSE b/LICENSE index 3beac51..eacc545 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,18 @@ MIT License -Copyright (c) 2021 HASwitchPlate +Copyright (c) 2021 Allen Derusha allen@derusha.org -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this hardware, +software, and associated documentation files (the "Product"), to deal in the Product without +restriction, including without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Product, and to permit persons to whom the +Product is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Product. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THE PRODUCT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE PRODUCT OR THE USE OR OTHER DEALINGS IN THE PRODUCT. \ No newline at end of file diff --git a/Nextion_HMI/HASwitchPlate-Enhanced.tft b/Nextion_HMI/HASwitchPlate-Enhanced.tft index d40b6c284a5dfe3762a77e70dc13cabd2366da3e..00f9c4762ccbc31c517d03c2b6c846dfc9322091 100644 GIT binary patch delta 62042 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 IE3e|uKVV-%MF0Q* delta 61569 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 Ne{|vBHC5=j2>{-#i|_zkhQ$=QhvhYdQBk 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 V8)y&EK3t6Uz4d=ctGE~c{2$5?ve5tl delta 61575 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 ByJr9Z diff --git a/Nextion_HMI/HASwitchPlate-TJC.tft b/Nextion_HMI/HASwitchPlate-TJC.tft index c5af7688c8beb6c5d21842f14a46ccff188ee085..32f3ba57aa13de283bcb142b1c2de27c04571df9 100644 GIT binary patch delta 63452 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 diff --git a/Nextion_HMI/HASwitchPlate.HMI b/Nextion_HMI/HASwitchPlate.HMI index 516c2004770e1e08f76a7677bb413357a398d200..7091a17b2ab28e1e4323254d6947e9e381629691 100644 GIT binary patch delta 2609 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 delta 36185 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 diff --git a/images/hasp_Display_Text_and_Activate_Page.png b/images/hasp_Display_Text_and_Activate_Page.png deleted file mode 100644 index 954d47fcdb162101190dec167e202cc0b23ebc2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2391 zcmZveXgD&GX`Uaqjt@`#Ilp?>+a;DfaaytEpmD zK_HNtr-$n)g_kMJ4X&hEckDhYD;zlG6qy9-e4-~+1dte_7ZC*NxrF=}235p}M30~p z5J>&OKL#F4xDlz?L^Iu}OuvL^=7q52C=fY0Dk?sOk-(&X3s)fUC!VfEe-?ec{(SXp zyL$eu8Y{C};jAdqeukngpToN>jc+)}Xs^$`QZVkh>9-l z0%v4}^b_QGN+iX>hEdN)ZIp^93+GAA9kZG7<(X6;;^YBWh^nf{I5E0gme{ycJO12n`-#%1+!;c2v zZP0t8ayD43f!`TIZy=?bf|--YmSmpuy>2fuIERWKcdkiL0|`0b!11516MxkGyM#-% zu%?62Aj(SJTzfOeu?tc(w&3@neDzW7>N@^&FE>TW2)C@oicbwvcR18kkk8+@g164} zrMh1FBW-%Ht$LD}W-7d|6jc1>GVB}=3qP{Y;#m}NYSSe8bzPN1Ozl=)5gg4w?Vppq zPCV*;OEbOspBi{`S&4WgPLQZ$+aBn0k#+xeDWk9~=2%`|ob%hzacI`WYU#bJp_n8R zSSiFqY|Mb9&m6X0S!m}&ybPgp)ojQnuUA!sUHIbb3EPaLUg4@34PkkI9l%YklpXU? zO*gY#7&tkCm(Kt2o%UO)xs5>sU_WA;VSMNK)Iqa!{e3T$nlB3~#DZbus?dFrWy(Ws zl<~kq>Wv;6#dE(8|3vU8-@&r#*+Z)=Tk)cDDvFTILJ(7?!AFKh@@s3%kMPAeNJtu` zEJwnio(*EJ)9P ziNVYqS^Yo?B!E#bmlA?9l$hrq&GkXCp`9-2{+rb?5WLP_?k6yW#y! zGQydC4S*=!%oTI5yOfGq>>W#4Ozh{G%9e)1$eMGjl!Uq-%o>^ltGw_COf20gWchp- zhUs}yrEF{ZlZeN0RGTIZ}ukVSWX2$VF$9BXqM%?NSUG4XS9$o*JB zo-w$J7+p-%fG5e`K%uyCS*)2kqw8+$ugp`nqSDq^Z$wH0ne)lL)N6XX3ulVv9wLZ!zw1Z1iknSC zGm^-5&;3r3mkEVFhw1T(o}RhSxMG1#32d}s_~*H+FaBs}wURH}Ls=GbV0yQKQQT{e z_Ty;2#uhKNh;gF^W$3cU`<^mw;A@t(Zm4-d4c$)0LM}v>utz-uk0Vx^jqzs ze^CKr0jBrt-f(FvRE@Emm#6GakU_xF;^c#a`+i(M?|lp-Iui4RG1oF57;V3JehZZS zqImM!C>e>x1^V0U<~U)_0|hR@{G75Jti%>o+&DSP(XfO6ffKymgYgcO6ttrknjpBPqm5(4n^a!a82BTt0!XTu z3LNbQhNk~?S{YU3s4>D$b_%22#YWVLi`Sz==coo>Fq)$64lp#&2@xSwE8@+EMLVz> zEu3bP#?_Y&rO~kO`(CYx_9*@+RC51ju1(jZ)TKEp`MuG~gRPOa{YPCtAJMx_co8dT zn>lG4(EU9^r|#f8n0p+z%-@J(?4#cdsTLI+)V$ndxj{?>f^s1OjOT>5VYHcgRJsZ= z@2ak5$j^FIWPq#N(r)n69(j(>pbnHZ-8xLpfvnE<%hzwXaQ_A=`G%uuDuh=@$$$Py zv+X1`0(sjlsX0^nHYe&&bj)ABK4KzJ*F@oLr~(Wv_ogjH?24H^a68uL;xk;~SM&KdI~(tmLUpp6T<#t{kz|lS;OVVFhFeP$=413H zO6?_TsY#aA0On3OBK`k~tjtf_w8qUoQ4AuT9lx=)xtUG$GjZ(N3Di~0Js?jvZ`V#z GDCfV<=t`3S diff --git a/images/hasp_Display_Text_and_Trigger_Scene.png b/images/hasp_Display_Text_and_Trigger_Scene.png deleted file mode 100644 index a1bd7323a79c3ecf6413148c89b9ba3bd0fdc3da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1935 zcmZ`)do8m1 zKuGd&M=yC^l)DogB9EK+EvP(!qrF^6pxS=yj2ys10CxZcdX$0K3Q&+^<*4J7Xb=e1 z@wbD!BP#>t#ho!uXJWh~gJZ4-(1SoO^q`kBj6KvVJ;s`pEXi- zjLyRv*j;}eBnzN(vB8hqT57yhU$Oeq99BX@!!q^t?%&dF+59P!;!4)tmX(3-km@(W zBml3jJ54nviC*|5^Eg#-K*?L3jpFZzX}LMUZSqppV({qyZ@8Myvy&T&uee#o{4};{+A|3tMXbS)h{rxl$8FKcBf8tP?V6J#OhJeE#F*x3XrD z?4iB)5t!tZM_CqfFKjyzQR!=#?MsI;9ag>^fTfS0`3*eG=m-mpE*&VD;sc1&`eI0~ zYfJZNbr1#`{LSn0CW3^*jdZP7wjh2>}R8= z0=pd2kDV7s+-!Q^e9V;3M8+7HBdJ7SBo%jnHsZwNx5)%JM)|S(H6qvlwD3&IqeFlW zF0B=stJ5~g%(j3SKnWKF?C)>2{d+AhSs5{#s}HBn&b%^IE+Ld-TJ42o{U$YfD!=}hL%qAp4FvD;`Z|kjCfOO-}oD+1EHlk_-%1`5~>;uxh!n$Ha z1cU?Y)t$bNX{RN9?b0U0BA*>tn(-*e4cz(1uH|ZMyMR zl!i6toh1(&5cfGWg&#VU=6+C-xhxdy|3UKCGQO-SD2aR6xi6uszI_c zSBl77f5PljpVnJ=yUR5yWVGkpx zd4^b&6I*BKLS3EJAmFuGfgZh#N?ywkPx7}c$^q}BIIQdTPDSOXB1O-~GT&GDRwKFER9ETJseAFR6d*^0ThDymSO z!QsDfT6sZ!S*wm(#@4h`;G~V<2f@DkqlVHR7||YpseDQFu*w_>S zGq34kgaDkE5Z1j_H)hQ)!6`Y<6KKlACv;ljgdd=RwTx{rT$SYRF#4qCWje4ztI(nq zmYqv+^-#v(p>@{Kgp>I;SF-{3p^_-eU4$FhgV-Lw8xX(VGxJYypZrC!s^Le=SJ&O> zTL0U9@7X{E{_Q7sQL=<5d(wE5(`zKu=$RC8HW3)=3&#lsu4W(uKBzLhy|?bMS{QVX z@iafauKSDUC?d`rrn7|?MY6(+8B#r1qDd{9AmS7~XIOC5*;2o(8C!VD4q4UG^{wKZ zDwH-{+NANd5ebztdso(FZ0C$e?;)!dFZJ_yCwC>7jiKfL{RnzO)Sy6cTYA0i1*Q57 zrQ!-{lLlZ9_i3tx+7MbIDSofA{>*V}v*A}XS0`f=G3y1_AmC-AT zmg~B==10jiCCoRg@PEz5Eaoi-AnYGI9v!K&e;S)nND|egsS$?G8u(wl%XcrA^EXkK zwSMn}#axl_fk#6qq~VXz3}l9WPrOp|E#6sxSjj{_S2EYK_|lf3(cd+G+s)+mf*qkB z=wi`p;#$foN@sM}5?~zQ4INVzf zbe5?a)wsT9DNOy-WKgD{xuVV{>Y%S^7LKdHi(TOxpmRr2+a0cjeQUa~^N1Xz