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 d40b6c2..00f9c47 100644 Binary files a/Nextion_HMI/HASwitchPlate-Enhanced.tft and b/Nextion_HMI/HASwitchPlate-Enhanced.tft differ diff --git a/Nextion_HMI/HASwitchPlate-Inverted.tft b/Nextion_HMI/HASwitchPlate-Inverted.tft index 3f0395c..225f0fe 100644 Binary files a/Nextion_HMI/HASwitchPlate-Inverted.tft and b/Nextion_HMI/HASwitchPlate-Inverted.tft differ diff --git a/Nextion_HMI/HASwitchPlate-TJC.HMI b/Nextion_HMI/HASwitchPlate-TJC.HMI index 2867608..a000fca 100644 Binary files a/Nextion_HMI/HASwitchPlate-TJC.HMI and b/Nextion_HMI/HASwitchPlate-TJC.HMI differ diff --git a/Nextion_HMI/HASwitchPlate-TJC.tft b/Nextion_HMI/HASwitchPlate-TJC.tft index c5af768..32f3ba5 100644 Binary files a/Nextion_HMI/HASwitchPlate-TJC.tft and b/Nextion_HMI/HASwitchPlate-TJC.tft differ diff --git a/Nextion_HMI/HASwitchPlate.HMI b/Nextion_HMI/HASwitchPlate.HMI index 516c200..7091a17 100644 Binary files a/Nextion_HMI/HASwitchPlate.HMI and b/Nextion_HMI/HASwitchPlate.HMI differ diff --git a/Nextion_HMI/HASwitchPlate.tft b/Nextion_HMI/HASwitchPlate.tft index ccc100c..3108873 100644 Binary files a/Nextion_HMI/HASwitchPlate.tft and b/Nextion_HMI/HASwitchPlate.tft differ 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 954d47f..0000000 Binary files a/images/hasp_Display_Text_and_Activate_Page.png and /dev/null differ 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 a1bd732..0000000 Binary files a/images/hasp_Display_Text_and_Trigger_Scene.png and /dev/null differ diff --git a/update/version-insecure.json b/update/version-insecure.json deleted file mode 100644 index 1438e4c..0000000 --- a/update/version-insecure.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "d1_mini": { - "version": "0.41", - "firmware": "http://haswitchplate.com/update/HASwitchPlate.ino.d1_mini.bin" - }, - "NX3224T024_011R": { - "version": 3, - "firmware": "http://haswitchplate.com/update/HASwitchPlate.tft" - }, - "NX3224K024_011R": { - "version": 3, - "firmware": "http://haswitchplate.com/update/HASwitchPlate-Enhanced.tft" - }, - "TJC3224T024_011R": { - "version": 3, - "firmware": "http://haswitchplate.com/update/HASwitchPlate-TJC.tft" - } -} \ No newline at end of file diff --git a/update/version.json b/update/version.json index b92c1cb..37fd258 100644 --- a/update/version.json +++ b/update/version.json @@ -1,18 +1,18 @@ { "d1_mini": { - "version": "0.41", - "firmware": "https://raw.githubusercontent.com/aderusha/HASwitchPlate/master/Arduino_Sketch/HASwitchPlate.ino.d1_mini.bin" + "version": "1.00", + "firmware": "https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/Arduino_Sketch/HASwitchPlate.ino.d1_mini.bin" }, "NX3224T024_011R": { "version": 3, - "firmware": "https://raw.githubusercontent.com/aderusha/HASwitchPlate/master/Nextion_HMI/HASwitchPlate.tft" + "firmware": "https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/Nextion_HMI/HASwitchPlate.tft" }, "NX3224K024_011R": { "version": 3, - "firmware": "https://raw.githubusercontent.com/aderusha/HASwitchPlate/master/Nextion_HMI/HASwitchPlate-Enhanced.tft" + "firmware": "https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/Nextion_HMI/HASwitchPlate-Enhanced.tft" }, "TJC3224T024_011R": { "version": 3, - "firmware": "https://raw.githubusercontent.com/aderusha/HASwitchPlate/master/Nextion_HMI/HASwitchPlate-TJC.tft" + "firmware": "https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/Nextion_HMI/HASwitchPlate-TJC.tft" } } \ No newline at end of file