THIS IS A OPEN SOURCE PROJECT THERE ARE NO FEES
Here is what I did:
Install Firmware
- Connect display with your computer
- Flash the Firmware: Use Chrome Browser while you on the Nightly Build-Site Select âGuition ESP32-S3-4848S040â and Install
- Setting Up Wifi: Follow Instructions on the screen
Install HomeAssistant Components
- HACS: Install HACS if you havenât already
- MQTT: Install and setup Home Assistant Add-on: Mosquitto broker if you havenât already (OpenHasp and the Display communicate via MQTT)
- openHASP Custom Component: Install The OpenHASP Component from within HACS
Set up HomeAssistant
- Make sure your Display is running and reachable (Default setup shows with text âplateâ on the top left corner of the screen and a popup with the actual IP-Adress).
- Go to shown IP-Adress with browser goto: http://your_ip/config/mqtt and fill in mqtt credentials from step 2 (see above)
- Got to shown IP-Adress with browser goto: http://your_ip/edit delete the pre-defined
pages.jsonl
file (Optional, otherwise Display loads this during startup)
- Go to shown IP-Adress with browser goto: http://your_ip/config/gpio and add:
GPIO Output
PIN: 40 (May be different on other Displays)
TYPE: Power Relay
Groupe: None
Value: Normal
â I had issues with entity naming when I skipped this step
- SetUp your display within Homeassistant detailed information here and follow the example weâll edit the files later on. If everything works as aspected the display will be auto-discovered by OpenHASP-Component
- Add a HA-Template sensor in configuration.yaml and edit to your needs (May use http://gridcalculator.dk/ to calculate col and gutter values)
template:
- binary_sensor:
- name: Display settings
unique_id: 1b3a3dae-fd0c-4f47-9c8b-5b680478a977 # https://www.uuidgenerator.net/
state: "{{ now() }}"
attributes:
update_automation: "automation.update_display_data" # add a the automation entity_id from step 3 before
update_time: "80" # sending the config via mqtt needs some time to complete. This stops the automation from re.run before sending config is finished
display_w: "480"
display_h: "480"
grid_cols: "12" # increase for more resolution of object
grid_rows: "12" # increase for more resolution of object
grid_gutter: "8" # This looked nice for me
grid_margin: "4" # This looked nice for me
bg_color: "#000000"
primary_color: "#4193d5"
secondary_color: "#ee9f52"
accent_color: "#A175C4"
success_color: "#6cbe58"
warning_color: "#d67430"
error_color: "#e25628"
radius: "4"
- If youâre done you should have a working display which is integrated in Homeassistant and comunicates via MQTT as well as a New Template Sensor with the given attributes
- Further reading if everything worked as aspected
Customizing
OpenHASP is highly customizable. Every Object can be set pixel perfect. This means you have to define every Width/Height x-and y-position.
To get rid of this I wrote I simple Jinja-Template. So I set Up dimensions with a grid system instead of pixel values. EXAMPLE:
Get Postion and size like this
{% import 'openhasp.jinja' as grid %}
w = {{grid.w(1)}}
h = {{grid.h(1)}}
x = {{grid.x(1)}}
y = {{grid.y(1)}}
This Example generates the size (1x1) and coordinates ( 1st from left, 1ist from top) for the given display settings
Get colors like this
color = {% from 'openhasp.jinja' import color %}{{color('primary')}}
light_color = {% from 'openhasp.jinja' import color %}{{color('primary_light')}}
dark_color = {% from 'openhasp.jinja' import color %}{{color('primary_dark')}}
This Example generates Color Values. So if you want to change colors, just change the attribute of the Display settings sensor instead of changing the openhasp config
Try yourself
- In the folder âcustom_templatesâ add a new file:
openhasp.jinja
{%- macro grid() -%}
{%- set settingsSensor = 'binary_sensor.display_settings' -%}
{%- set dw = (state_attr(settingsSensor, 'display_w') | default(240)) | int -%}
{%- set dh = (state_attr(settingsSensor, 'display_h') | default(240)) | int -%}
{%- set cols = (state_attr(settingsSensor, 'grid_cols') | default(6)) | int -%}
{%- set rows = (state_attr(settingsSensor, 'grid_rows') | default(6)) | int -%}
{%- set margin = (state_attr(settingsSensor, 'grid_margin') | default(10)) | int -%}
{%- set gutter = (state_attr(settingsSensor, 'grid_gutter') | default(10)) | int -%}
{%- set radius = (state_attr(settingsSensor, 'radius') | default(5)) | int -%}
{{-
{
'w': (dw - (2 * margin) - ((cols-1) * gutter)) / cols,
'h': (dh - (2 * margin) - ((rows-1) * gutter)) / rows,
'cols' : cols,
'rows' : rows,
'margin' : margin,
'gutter' : gutter,
'display_width' : dw,
'display_height' : dh,
'radius': radius
} | to_json
-}}
{%- endmacro -%}
{%- macro w(w) -%}
{%- set gutter = (grid() | from_json).gutter | default(10) | int -%}
{%- set errors = namespace(w=[]) %}
{%- if w > (grid() | from_json).cols or w <= -1 -%}
{% set errors.w = 'cols must be between 1 and ' + (grid() | from_json).cols | string %}
{%- endif -%}
{{- errors.w if errors.w | count > 0 else (w * (grid() | from_json).w | int) + ((w-1) * gutter | int) -}}
{%- endmacro -%}
{%- macro h(h) -%}
{%- set gutter = (grid() | from_json).gutter | default(10) | int -%}
{%- set errors = namespace(h=[]) %}
{%- if h > (grid() | from_json).rows or h <= -1 -%}
{% set errors.h = 'rows must be beetween 1 and ' + (grid() | from_json).rows | string %}
{%- endif -%}
{{- errors.h if errors.h | count > 0 else (h * (grid() | from_json).h | int) + ((h-1) * gutter | int) -}}
{%- endmacro -%}
{%- macro x(x) -%}
{%- set x = x-1 | default(1) -%}
{%- set margin = (grid() | from_json).margin | default(10) | int -%}
{%- set gutter = (grid() | from_json).gutter | default(10) | int -%}
{%- set width = w(x) | int -%}
{{- (margin if x == 0 else (margin + width + gutter)) if width is number else width -}}
{%- endmacro -%}
{%- macro y(y) -%}
{%- set y = y-1 | default(1) -%}
{%- set margin = (grid() | from_json).margin | default(10) | int -%}
{%- set gutter = (grid() | from_json).gutter | default(10) | int -%}
{%- set height = h(y) | int -%}
{{- (margin if y == 0 else (margin + height + gutter)) if height is number else height -}}
{%- endmacro -%}
{%- macro AdjustColor(hex, brightness) -%}
{%- set brightness = brightness|default(0.1) -%}
{%- set hex = hex|replace('#', '')|replace('/[^0-9a-f]/gi', '') -%}
{%- if hex|length < 6 -%}
{%- set hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2] -%}
{%- endif -%}
{%- set color = namespace(rgb='') -%}
{%- set color.rgb = '#' -%}
{%- for i in range(0, 6, 2) -%}
{%- set c = hex[i:i+2]|int(base=16) -%}
{%- set c = (c + (c * brightness))|round|int -%}
{%- set c = 0 if c < 0 else ( 255 if c > 255 else c) -%}
{%- set c = "%02x"|format(c) -%}
{%- set color.rgb = color.rgb + c -%}
{%- endfor -%}
{{- color.rgb -}}
{%- endmacro -%}
{%- macro color(name) -%}
{%- set s = name.split("_") -%}
{%- set base = state_attr('binary_sensor.display_settings', s[0]+'_color') | default('#000000') -%}
{%- if s | count > 1 and s[1] == 'light' -%}
{{ AdjustColor(base, 0.2) }}
{%- elif s | count > 1 and s[1] == 'dark' -%}
{{ AdjustColor(base, -0.2) }}
{%-else-%}
{{ base -}}
{%- endif %}
{%- endmacro -%}
- In your plate.json file:
[
"SEITE 0 - SETTINGS",
{
"page": 1,
"id": 0,
"prev": 4
},
"SEITE 0 - PREVIOUS -BUTTON",
{
"page": 0,
"id": 1,
"obj": "btn",
"outline_opa": 0,
"border_opa": 0,
"text_font": 32,
"toggle": false,
"action": "prev"
},
"SEITE 0 - HOME - BUTTON",
{
"page": 0,
"id": 2,
"obj": "btn",
"outline_opa": 0,
"border_opa": 0,
"text_font": 32,
"toggle": false,
"action": {
"down": "back",
"hold": "restart"
}
},
"SEITE 0 - NEXT - BUTTON",
{
"page": 0,
"id": 3,
"obj": "btn",
"text": "\uE054",
"outline_opa": 0,
"border_opa": 0,
"text_font": 32,
"action": "next",
"toggle": false
},
"SEITE 1 - CONTAINER",
{
"page": 1,
"id": 2,
"obj": "obj",
"border_opa": 0,
"bg_opa": 0,
"click": 0
}
]
- In your homeassistant
configuration.yaml
add:
openhasp:
display02: # depends on you given device Name!!!
objects:
# SEITE 0
- obj: "p0b0" # SETTINGS
properties:
"jsonl": >
{% from 'openhasp.jinja' import color %}
{{
{
'bg_color' : color('bg')
} |to_json |string
}}
- obj: "p0b1" # PREVIOUS - BUTTON"
properties:
"jsonl": >
{% from 'openhasp.jinja' import grid,w,h,x,y,color %}
{{
{
'w': w(4)|int,
'h': h(2)|int,
'x': x(1)|int,
'y': y(11)|int,
'radius': (grid() | from_json).radius |int,
'bg_color': color('primary'),
'bg_color02': color('primary_light'),
'text': "\uE04D"
} |to_json |string
}}
- obj: "p0b2" # HOME - BUTTON
properties:
"jsonl": >
{% from 'openhasp.jinja' import grid,w,h,x,y,color %}
{{
{
'w': w(4)|int,
'h': h(2)|int,
'x': x(5)|int,
'y': y(11)|int,
'radius': (grid() | from_json).radius |int,
'bg_color': color('primary'),
'bg_color02': color('primary_light'),
'text': "\uE6A1"
} |to_json |string
}}
- obj: "p0b3" # NEXT - BUTTON
properties:
"jsonl": >
{% from 'openhasp.jinja' import grid,w,h,x,y,color %}
{{
{
'w': w(4)|int,
'h': h(2)|int,
'x': x(9)|int,
'y': y(11)|int,
'radius': (grid() | from_json).radius |int,
'bg_color': color('primary'),
'bg_color02': color('primary_light'),
'text': "\uE054"
} |to_json |string
}}
# SEITE 1
- obj: "p1b0" # SETTINGS
properties:
"jsonl": >
{% from 'openhasp.jinja' import color %}
{{
{
'bg_color': color('bg')
} |to_json |string
}}
- obj: "p1b2" # CONTAINER
properties:
"jsonl": >
{% from 'openhasp.jinja' import grid,h %}
{{
{
'w': (grid() | from_json).display_width,
'h': h(10)|int,
'x': 0|int,
'y': 0|int
} |to_json |string
}}
-
Restart The Display and/or reload_config_entry for your device to see your changes
-
From now on youâre on your own. Feel free to share yours
Here is my display: