diff --git a/Home_Assistant/blueprints/hasp_Display_Weather_Forecast.yaml b/Home_Assistant/blueprints/hasp_Display_Weather_Forecast.yaml index af3dd27..21d5b26 100644 --- a/Home_Assistant/blueprints/hasp_Display_Weather_Forecast.yaml +++ b/Home_Assistant/blueprints/hasp_Display_Weather_Forecast.yaml @@ -122,7 +122,7 @@ blueprint: domain: weather forecast_interval: name: "Forecast interval" - description: 'Forecast interval, one of "hourly", "twice daily", or "daily"' + description: 'Forecast interval, one of "hourly", "twice daily", or "daily". Not all weather providers will offer all options.' default: "daily" selector: select: diff --git a/Home_Assistant/blueprints/hasp_Display_Weather_Forecast_High_Low.yaml b/Home_Assistant/blueprints/hasp_Display_Weather_Forecast_High_Low.yaml new file mode 100644 index 0000000..ee6e6d4 --- /dev/null +++ b/Home_Assistant/blueprints/hasp_Display_Weather_Forecast_High_Low.yaml @@ -0,0 +1,459 @@ +blueprint: + name: "HASPone p[x].b[y] displays the weather forecast High and Low temperature" + description: | + + ## Blueprint Version: `1.06.00` + + ## Description + + A HASPone button displays the high and low temperatures from a selected weather forecast. + + ![Preview](https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/images/hasp_Display_Weather_Forecast.png) + + ## HASPone Page and Button Reference + + The images below show each available HASPone page along with the layout of available button objects. + +
+ + | Page 0 | Pages 1-3 | Pages 4-5 | + |--------|-----------|-----------| + | ![Page 0](https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/images/NextionUI_p0_Init_Screen.png) | ![Pages 1-3](https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/images/NextionUI_p1-p3_4buttons.png) | ![Pages 4-5](https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/images/NextionUI_p4-p5_3sliders.png) | + + | Page 6 | Page 7 | Page 8 | + |--------|--------|--------| + | ![Page 6](https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/images/NextionUI_p6_8buttons.png) | ![Page 7](https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/images/NextionUI_p7_12buttons.png) | ![Page 8](https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/images/NextionUI_p8_5buttons+1slider.png) | + + | Page 9 | Page 10 | Page 11 | + |--------|---------|---------| + | ![Page 9](https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/images/NextionUI_p9_9buttons.png) | ![Page 10](https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/images/NextionUI_p10_5buttons.png) | ![Page 11](https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/images/NextionUI_p11_1button+1slider.png) + +
+ + ## HASPone Font Reference + +
+ + The Nextion display supports monospaced and proportional fonts. For monospace fonts, the HASPone 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/HASwitchPlate/HASPone/blob/main/images/hasp-fontawesome5.html) + + ### Font examples + + ![HASPone Fonts 0-3](https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/images/NextionUI_Fonts_0-3.png) ![HASPone Fonts 4-7](https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/images/NextionUI_Fonts_4-7.png) ![HASPone Fonts 8-10](https://raw.githubusercontent.com/HASwitchPlate/HASPone/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 | + +
+ + domain: automation + input: + haspdevice: + name: "HASPone Device" + description: "Select the HASPone device" + selector: + device: + integration: mqtt + manufacturer: "HASwitchPlate" + model: "HASPone v1.0.0" + hasppage: + name: "HASPone Page" + description: "Select the HASPone page (1-11) for the forecast. Refer to the HASPone Page and Button reference above." + default: 1 + selector: + number: + min: 1 + max: 11 + mode: slider + unit_of_measurement: page + haspbutton: + name: "HASPone Button" + description: "Select the HASPone button (4-15) for the forecast. Refer to the HASPone 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_interval: + name: "Forecast interval" + description: 'Forecast interval, one of "hourly", "twice daily", or "daily". Not all weather providers will offer all options.' + default: "daily" + selector: + select: + options: + - "hourly" + - "twice_daily" + - "daily" + forecast_index: + name: "Forecast index" + description: 'Select a specific forecast, the next time interval will be index "0". Increment this number for future forecasts' + default: 0 + selector: + number: + min: 0 + max: 48 + mode: slider + unit_of_measurement: index + font_select: + name: "Font" + description: "Select the font for the displayed text. You probably want to leave this as 10, refer to the HASPone Font Reference above." + default: "10 - Noto Sans Bold 80" + 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: + selected_fgcolor: + name: "Selected foreground color" + description: 'Selected foreground color 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 + selected_bgcolor: + name: "Selected background color" + description: 'Selected background color in Nextion RGB565 format (see "Nextion color codes" above for reference). -1 = Current theme selected background color.' + default: -1 + selector: + number: + min: -1 + max: 65535 + mode: slider + unselected_fgcolor: + name: "Unselected foreground color" + description: 'Unselected foreground color in Nextion RGB565 format (see "Nextion color codes" above for reference). -1 = Current theme unselected foreground color.' + default: -1 + selector: + number: + min: -1 + max: 65535 + mode: slider + unselected_bgcolor: + name: "Unselected background color" + description: 'Unselected background color in Nextion RGB565 format (see "Nextion color codes" above for reference). -1 = Current theme unselected background color.' + default: -1 + selector: + number: + min: -1 + max: 65535 + mode: slider + +mode: parallel +max_exceeded: silent + +variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {%- endif -%} + {%- endfor -%} + hasppage: !input hasppage + haspbutton: !input haspbutton + weather_provider: !input weather_provider + forecast_interval: !input forecast_interval + forecast_index: !input forecast_index + 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 + selected_fgcolor: !input selected_fgcolor + selected_bgcolor: !input selected_bgcolor + unselected_fgcolor: !input unselected_fgcolor + unselected_bgcolor: !input unselected_bgcolor + haspobject: '{{ "p[" ~ hasppage ~ "].b[" ~ haspbutton ~ "]" }}' + commandtopic: '{{ "hasp/" ~ haspname ~ "/command/" ~ haspobject }}' + 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: >- + {%- if (selected_fgcolor|int) >= 0 -%} + {{ selected_fgcolor }} + {%- else -%} + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int(default=255) / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + {%- endif -%} + selectedbg: >- + {%- if (selected_bgcolor|int) >= 0 -%} + {{ selected_bgcolor }} + {%- else -%} + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_selected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int(default=255) / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + {%- endif -%} + unselectedfg: >- + {%- if (unselected_fgcolor|int) >= 0 -%} + {{ unselected_fgcolor }} + {%- else -%} + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_foreground_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int(default=255) / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + {%- endif -%} + unselectedbg: >- + {%- if (unselected_bgcolor|int) >= 0 -%} + {{ unselected_bgcolor }} + {%- else -%} + {%- set color = namespace() -%} + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^light\..*_unselected_background_color(?:_\d+|)$") -%} + {%- set color.source=entity -%} + {%- endif -%} + {%- endfor -%} + {%- set brightness = state_attr(color.source, "brightness")|int(default=255) / 255 -%} + {%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%} + {%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%} + {%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%} + {{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }} + {%- endif -%} + +trigger_variables: + haspdevice: !input haspdevice + haspname: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} + {{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}} + {%- endif -%} + {%- endfor -%} + haspsensor: >- + {%- for entity in device_entities(haspdevice) -%} + {%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%} + {{ entity }} + {%- 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: + - service: weather.get_forecasts + target: + entity_id: !input weather_provider + data: + type: "{{forecast_interval}}" + response_variable: weather_forecast + - variables: + temphigh: '{{ weather_forecast[weather_provider]["forecast"][forecast_index]["temperature"] }}' + templow: '{{ weather_forecast[weather_provider]["forecast"][forecast_index]["templow"] }}' + text: "{{templow|int(default=0)}}° {{temphigh|int(default=0)}}°" + + - 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 is none) + 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) and ((selected_fgcolor|int) == -1) }}" + 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) and ((selected_bgcolor|int) == -1) }}" + 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) and ((unselected_fgcolor|int) == -1) }}" + 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) and ((unselected_bgcolor|int) == -1) }}" + sequence: + - service: mqtt.publish + data: + topic: "{{commandtopic}}.bco2" + payload: "{{trigger.payload}}"