[FEATURE,DOC] add vis elements, update doc

This commit is contained in:
smokyflex
2023-11-24 12:35:34 +01:00
parent b25a84d755
commit e03d9275bf
31 changed files with 765 additions and 1 deletions

View File

@@ -1,5 +1,7 @@
# pe1-modbus
NOTE: This project is not an official HA or HACS integration.
This project offers a guideline how a Fröling PE1 / Lambdatronic Pellet boiler can be integrated into Home Assistant (HA - https://www.home-assistant.io) using the builtin Modbus interface.
This repo also includes python scripts that use a modbus module to read registers from PE1 an then post them via MQTT to use inside Home Assistant but this is not necessary since HA has it's own Modbus interface where we can directly map PE1 registers to HA entities.
@@ -197,3 +199,38 @@ action:
Now we can use this dropdown via `input_select.heating_mode_select` and change the heating mode via the modbus interface!
We can also use the same approach to remote control the flow temeperature set point and the hotwater boiler temperature setpoint.
## Visualization
The following shows some visualization ideas, using the new entities we have setup.
### Heating Curve (Flow Target Setpoint)
Most HA visualization options for displaying line and scatter plots are designed to display time-based/historic data from HA entities. The `plotly-graph` card which can be installed via HACS however can be configured in a specific ways to not only use a time-based x-axis. This way we can use entities representing the heating curve lower and upper setpoints, along with the outside temperture and the target flow setpoint to construct a heating curve like shown below.
The plotly-graph configuration for this visualization can be found in `/visualization/heating_curve.yaml`.
![](img/pe1_heating_curve.png?raw=true)
### Historic Data
![](img/hotwater_history.png?raw=true)
![](img/buffer_temp_history.png?raw=true)
![](img/heating_flow_history.png?raw=true)
![](img/pellet_consumption.png?raw=true)
For some of those plots the `apexcharts-card` was used which you can integrate via HACS.
As the HA energy dashboard does not (yet) offer support for something like pellet consumption, since it does not support weight metrics like g/kg etc. we can use a `Utility Meter` for that purpose. The pellet consumption plot uses the modbus entity `modbus_pe1_pellet_consumption_kg` in combination with a Utility Meter which can be setup in the Helpers section of HA. The Utility meter enables us to display only the delta of consumption for each day, since the original modbus_pe1_pellet_consumption_kg entity is a total increasing count.
### System Status
HA offers the `picture-elements` lovelance card, which we can use to display custom images, entity state labels, icons and more. Using draw.io or even the Microsoft Word, we can draw shapes representing our heating system components and overlay some of our entities to achieve something like shown below.
![](img/pe1_system.gif?raw=true)
The picture-element configuration for this visualization can be found in `/visualization/system_status.yaml`.
The corresponding images used for this visualization can be found in the /img directory.
If you want to achieve this exact visualization, some additional template sensors are needed that can be found in the `/template.yaml`.

BIN
img/boiler.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
img/buffer_c.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

BIN
img/buffer_ch.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

BIN
img/buffer_cw.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

BIN
img/buffer_h.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

BIN
img/buffer_hw.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

BIN
img/buffer_temp_history.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

BIN
img/buffer_w.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

BIN
img/buffer_wc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

BIN
img/buffer_wh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

BIN
img/e-p-hot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
img/e-pat-off.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
img/e-pat-on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
img/empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

BIN
img/hotwater_history.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

BIN
img/pe1_heating_curve.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
img/pe1_schematic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
img/pe1_system.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

BIN
img/pellet_consumption.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -165,3 +165,129 @@
{% else %}
mdi:alert-circle
{% endif %}
- name: Visualization Is Heating Active
unique_id: "visualization_heating_active"
state: >
{% if states('sensor.modbus_pe1_flow_temperature_target') | int > 0%}
true
{% else %}
false
{% endif %}
- name: Visualization Is Buffer Cold
unique_id: "visualization_buffer_cold"
state: >
{% if states('sensor.modbus_pe1_buffer_temperature_bottom') | int < 30 and states('sensor.modbus_pe1_buffer_temperature_top') | int < 30%}
true
{% else %}
false
{% endif %}
- name: Visualization Is Buffer Cold Warm
unique_id: "visualization_buffer_cold_warm"
state: >
{% if states('sensor.modbus_pe1_buffer_temperature_bottom') | int < 30 and states('sensor.modbus_pe1_buffer_temperature_top') | int >= 30 and states('sensor.modbus_pe1_buffer_temperature_top') | int < 50%}
true
{% else %}
false
{% endif %}
- name: Visualization Is Buffer Cold Hot
unique_id: "visualization_buffer_cold_hot"
state: >
{% if states('sensor.modbus_pe1_buffer_temperature_bottom') | int < 30 and states('sensor.modbus_pe1_buffer_temperature_top') | int >= 50%}
true
{% else %}
false
{% endif %}
- name: Visualization Is Buffer Warm Cold
unique_id: "visualization_buffer_warm_cold"
state: >
{% if states('sensor.modbus_pe1_buffer_temperature_bottom') | int >= 30 and states('sensor.modbus_pe1_buffer_temperature_bottom') | int < 50 and states('sensor.modbus_pe1_buffer_temperature_top') | int < 30%}
true
{% else %}
false
{% endif %}
- name: Visualization Is Buffer Warm
unique_id: "visualization_buffer_warm"
state: >
{% if states('sensor.modbus_pe1_buffer_temperature_bottom') | int >= 30 and states('sensor.modbus_pe1_buffer_temperature_bottom') | int < 50 and states('sensor.modbus_pe1_buffer_temperature_top') | int >= 30 and states('sensor.modbus_pe1_buffer_temperature_top') | int < 50%}
true
{% else %}
false
{% endif %}
- name: Visualization Is Buffer Warm Hot
unique_id: "visualization_buffer_warm_hot"
state: >
{% if states('sensor.modbus_pe1_buffer_temperature_bottom') | int >= 30 and states('sensor.modbus_pe1_buffer_temperature_bottom') | int < 50 and states('sensor.modbus_pe1_buffer_temperature_top') | int >= 50%}
true
{% else %}
false
{% endif %}
- name: Visualization Is Buffer Hot Warm
unique_id: "visualization_buffer_hot_warm"
state: >
{% if states('sensor.modbus_pe1_buffer_temperature_top') | int >= 30 and states('sensor.modbus_pe1_buffer_temperature_top') | int < 50 and states('sensor.modbus_pe1_buffer_temperature_bottom') | int >= 50%}
true
{% else %}
false
{% endif %}
- name: Visualization Is Buffer Hot
unique_id: "visualization_buffer_hot"
state: >
{% if states('sensor.modbus_pe1_buffer_temperature_bottom') | int >= 50 and states('sensor.modbus_pe1_buffer_temperature_top') | int >= 50 %}
true
{% else %}
false
{% endif %}
- name: Visualization Is Radiator Cold
unique_id: "visualization_radiator_cold"
state: >
{% if states('sensor.modbus_pe1_flow_temperature_actual') | int < 30%}
true
{% else %}
false
{% endif %}
- name: Visualization Is Radiator Warm
unique_id: "visualization_radiator_warm"
state: >
{% if states('sensor.modbus_pe1_flow_temperature_actual') | int >= 30 and states('sensor.modbus_pe1_flow_temperature_actual') | int < 40%}
true
{% else %}
false
{% endif %}
- name: Visualization Is Radiator Hot
unique_id: "visualization_radiator_hot"
state: >
{% if states('sensor.modbus_pe1_flow_temperature_actual') | int >= 40%}
true
{% else %}
false
{% endif %}
- name: Buffer Pump Status
unique_id: "visualization_buffer_pump_status"
state: >
{% if states('sensor.modbus_pe1_buffer_pump_control') | float(0) > 0%}
on
{% else %}
off
{% endif %}
icon: >
{% if this.state == 'on' %}
mdi:pump
{% else %}
mdi:pump-off
{% endif %}
- name: Boiler Pump Status
unique_id: "visualization_water_boiler_pump_status"
state: >
{% if states('sensor.modbus_pe1_water_boiler_pump_control') | float(0) > 0%}
on
{% else %}
off
{% endif %}
icon: >
{% if this.state == 'on' %}
mdi:pump
{% else %}
mdi:pump-off
{% endif %}

46
visualization/buffer.yaml Normal file
View File

@@ -0,0 +1,46 @@
type: custom:apexcharts-card
header:
show: true
title: Buffer Temperature
show_states: true
colorize_states: true
graph_span: 24hrs
all_series_config:
type: area
opacity: 0.1
stroke_width: 1
series:
- entity: sensor.modbus_pe1_buffer_temperature_top
name: Top
color: red
group_by:
func: avg
duration: 5min
yaxis_id: degrees
- entity: sensor.modbus_pe1_buffer_temperature_bottom
name: Bottom
color: orange
group_by:
func: avg
duration: 5min
yaxis_id: degrees
- entity: sensor.modbus_pe1_buffer_pump_control
name: Pump Control
type: line
curve: stepline
group_by:
func: max
duration: 10min
stroke_width: 1
color: green
opacity: 1
yaxis_id: state
yaxis:
- id: state
show: false
opposite: true
- id: degrees
show: true
apex_config:
grid:
show: false

View File

@@ -0,0 +1,88 @@
type: custom:plotly-graph
hours_to_show: current_day
title: Heating Flow Setpoint
layout:
dragmode: pan
annotations:
- 'y': $ex hass.states["sensor.modbus_pe1_flow_temperature_target"].state
x: $ex hass.states["sensor.modbus_pe1_outside_temperature"].state
text: >-
$ex hass.states["sensor.modbus_pe1_flow_temperature_target"].state + '°C
now'
showarrow: true
arrowcolor: lightgrey
arrowsize: 0.8
arrowwidth: 1.8
arrowside: end
yshift: 10
xaxis:
type: number
showlegend: false
title: Outside [°C]
yaxis:
fixedrange: true
showlabel: true
range:
- 0
- 100
title: Flow Setpoint [°C]
height: 300
margin:
r: 50
l: 80
t: 50
entities:
- entity: ''
x: $ex [-10, 10, hass.states["sensor.modbus_pe1_outside_temperature"].state]
'y': >-
$ex
[hass.states["sensor.modbus_pe1_heating_curve_setpoint_upper"].state,hass.states["sensor.modbus_pe1_heating_curve_setpoint_lower"].state]
line:
shape: line
color: lightgrey
dash: dot
width: 1
marker:
size:
- 5
- 5
symbol:
- circle
- circle
color:
- orangered
- orange
mode: lines+markers+text
text: >-
$ex [hass.states["sensor.modbus_pe1_heating_curve_setpoint_upper"].state +
'°C',hass.states["sensor.modbus_pe1_heating_curve_setpoint_lower"].state +
'°C']
textposition:
- top
- top
- bottom
hovertemplate: |
$fn ({ hass }) => '%{y}<extra></extra>'
showlegend: false
- entity: ''
x: $ex [hass.states["sensor.modbus_pe1_outside_temperature"].state]
'y': $ex [hass.states["sensor.modbus_pe1_flow_temperature_target"].state]
line:
shape: line
color: lightgrey
dash: dot
width: 1
marker:
size:
- 6
symbol:
- diamond
color:
- green
mode: markers
hovertemplate: |
$fn ({ hass }) => '%{y}<extra></extra>'
showlegend: false
raw_plotly_config: true
config:
displayModeBar: false

View File

@@ -0,0 +1,64 @@
type: custom:apexcharts-card
experimental:
color_threshold: true
header:
show: true
title: Heating Flow
show_states: true
colorize_states: true
graph_span: 24hrs
series:
- entity: sensor.modbus_pe1_flow_temperature_actual
name: Flow Actual
group_by:
func: avg
duration: 5min
color: orange
stroke_width: 0
opacity: 0.3
type: area
- entity: sensor.modbus_pe1_flow_temperature_target
name: Flow Target
color: green
group_by:
func: avg
duration: 5min
stroke_width: 2
opacity: 1
- entity: sensor.modbus_pe1_outside_temperature
name: Outside
color: steelblue
group_by:
func: avg
duration: 5min
stroke_width: 1
opacity: 1
- entity: sensor.sonoff_sensor_temperature
name: Foyer
color: violet
group_by:
func: avg
duration: 5min
stroke_width: 1
opacity: 1
- entity: sensor.sonoff_hygroscope_lr_temperature
name: Living Room
color: pink
group_by:
func: avg
duration: 5min
stroke_width: 1
opacity: 1
- entity: sensor.sonoff_hygroscope_gr_temperature
name: Guest Room
color: indianred
group_by:
func: avg
duration: 5min
stroke_width: 1
opacity: 1
apex_config:
grid:
show: false
legend:
show: false

View File

@@ -0,0 +1,46 @@
type: custom:apexcharts-card
header:
show: true
title: Hot Water
show_states: true
colorize_states: true
graph_span: 24hrs
series:
- entity: sensor.modbus_pe1_hotwater_temperature_top
name: Temperature
type: area
group_by:
func: avg
duration: 10min
color: orange
stroke_width: 0
opacity: 0.5
yaxis_id: degrees
- entity: sensor.modbus_pe1_water_boiler_pump_control
name: Pump Control
type: area
curve: stepline
stroke_width: 1
color: green
opacity: 0.5
yaxis_id: state
- entity: switch.smart_switch_23022396705558510d0248e1e9bb85e5_outlet
name: E-Patrone
transform: 'return x == ''on'' ? 100: 0;'
type: area
curve: stepline
stroke_width: 0
color: red
opacity: 0.5
yaxis_id: state
yaxis:
- id: state
show: false
opposite: true
- id: degrees
show: true
min: 33
max: 67
apex_config:
grid:
show: false

View File

@@ -0,0 +1,10 @@
chart_type: bar
period: day
type: statistics-graph
entities:
- sensor.pellets_consumption_daily
stat_types:
- change
days_to_show: 365
title: Pellets Consumption [kg]
hide_legend: true

View File

@@ -0,0 +1,347 @@
type: picture-elements
image: /local/empty.png
style: |
ha-card {
{% if is_state('sensor.buffer_pump_status','on') %}
--state-animation-1: rotation 2s linear infinite;
--state-color-1: steelblue;
{% else %}
--state-color-1: grey;
{% endif %}
{% if is_state('sensor.boiler_pump_status','on') %}
--state-animation-2: rotation 2s linear infinite;
--state-color-2: steelblue;
{% else %}
--state-color-2: grey;
{% endif %}
{% if states('sensor.modbus_pe1_furnace_status') in ['Heating', 'Heating up', 'Pre-heating', 'Ignition', 'Preparation'] %}
--state-animation-3: blink 2s linear infinite;
--state-color-3: red;
{% else %}
--state-color-3: grey;
{% endif %}
{% if is_state('switch.smart_switch_23022396705558510d0248e1e9bb85e5_outlet', 'on')%}
--state-animation-4: blink 2s linear infinite;
{% endif %}
{% if is_state('sensor.visualization_is_radiator_cold','true') %}
--state-color-radiator: grey;
{% elif is_state('sensor.visualization_is_radiator_warm','true') %}
--state-color-radiator: orange;
{% elif is_state('sensor.visualization_is_radiator_hot','true') %}
--state-color-radiator: orangered;
{% endif %}
}
@keyframes rotation {
0% {transform: translate(-50%, -50%) scale(0.8,0.8) rotate(0deg)}
100% {transform: translate(-50%, -50%) scale(0.8,0.8) rotate(360deg)}
}
@keyframes blink {
0% {opacity: 1;}
25% {opacity: 0.6;}
50% {opacity: 0.2;}
75% {opacity: 0.6;}
100% {opacity: 1;}
}
elements:
- type: image
image: /local/pe1_schematic.png
style:
top: 70%
left: 20%
width: 30%
- type: image
image: /local/boiler.png
style:
top: 75%
left: 85%
width: 20%
- type: image
entity: switch.smart_switch_23022396705558510d0248e1e9bb85e5_outlet
style:
top: 78%
left: 89%
width: 20%
state_image:
'on': /local/e-p-hot.png
'off': /local/e-pat-off.png
- type: conditional
conditions:
- entity: sensor.visualization_is_buffer_cold
state: 'true'
elements:
- type: image
image: /local/buffer_c.png
style:
top: 55%
left: 55%
width: 30%
- type: conditional
conditions:
- entity: sensor.visualization_is_buffer_cold_warm
state: 'true'
elements:
- type: image
image: /local/buffer_cw.png
style:
top: 55%
left: 55%
width: 30%
- type: conditional
conditions:
- entity: sensor.visualization_is_buffer_cold_hot
state: 'true'
elements:
- type: image
image: /local/buffer_ch.png
style:
top: 55%
left: 55%
width: 30%
- type: conditional
conditions:
- entity: sensor.visualization_is_buffer_warm_cold
state: 'true'
elements:
- type: image
image: /local/buffer_wc.png
style:
top: 55%
left: 55%
width: 30%
- type: conditional
conditions:
- entity: sensor.visualization_is_buffer_warm
state: 'true'
elements:
- type: image
image: /local/buffer_w.png
style:
top: 55%
left: 55%
width: 30%
- type: conditional
conditions:
- entity: sensor.visualization_is_buffer_warm_hot
state: 'true'
elements:
- type: image
image: /local/buffer_wh.png
style:
top: 55%
left: 55%
width: 30%
- type: conditional
conditions:
- entity: sensor.visualization_is_buffer_hot_warm
state: 'true'
elements:
- type: image
image: /local/buffer_hw.png
style:
top: 55%
left: 55%
width: 30%
- type: conditional
conditions:
- entity: sensor.visualization_is_buffer_hot
state: 'true'
elements:
- type: image
image: /local/buffer_h.png
style:
top: 55%
left: 55%
width: 30%
- type: conditional
conditions:
- entity: sensor.visualization_is_radiator_cold
state: 'true'
elements:
- type: image
image: /local/rad_off.png
style:
top: 23%
left: 19%
width: 25%
- type: conditional
conditions:
- entity: sensor.visualization_is_radiator_warm
state: 'true'
elements:
- type: image
image: /local/rad_warm_10.gif
style:
top: 23%
left: 19%
width: 25%
- type: conditional
conditions:
- entity: sensor.visualization_is_radiator_hot
state: 'true'
elements:
- type: image
image: /local/rad_hot_10.gif
style:
top: 23%
left: 19%
width: 25%
- type: state-icon
entity: sensor.modbus_pe1_system_status
style:
top: 92%
left: 10%
'--paper-item-icon-color': white
transform: translate(-50%,-50%) scale(0.8,0.8)
- type: state-icon
entity: sensor.modbus_pe1_heating_mode
style:
top: 92%
left: 16.5%
'--paper-item-icon-color': white
transform: translate(-50%,-50%) scale(0.8,0.8)
- type: state-icon
entity: input_select.heating_mode_select
style:
top: 92%
left: 16.5%
'--paper-item-icon-color': white
transform: translate(-50%,-50%) scale(0.8,0.8)
opacity: 0
- type: state-icon
entity: sensor.modbus_pe1_furnace_status
style:
top: 57%
left: 23.3%
'--paper-item-icon-color': var(--state-color-3)
animation: var(--state-animation-3)
transform: translate(-50%,-50%) scale(0.8,0.8)
- type: conditional
conditions:
- entity: sensor.visualization_is_heating_active
state: 'true'
elements:
- type: icon
entity: sensor.modbus_pe1_flow_temperature_target
icon: mdi:heat-wave
style:
top: 67%
left: 23.3%
color: red
opacity: 1
transform: translate(-50%,-50%) scale(0.8,0.8)
- type: conditional
conditions:
- entity: sensor.visualization_is_heating_active
state: 'false'
elements:
- type: icon
entity: sensor.modbus_pe1_flow_temperature_target
icon: mdi:heat-wave
style:
top: 67%
left: 23.3%
color: grey
opacity: 1
transform: translate(-50%,-50%) scale(0.8,0.8)
- type: state-icon
entity: sensor.modbus_pe1_pellet_fill_level
style:
top: 92%
left: 23.3%
transform: translate(-50%,-50%) scale(0.8,0.8)
- type: conditional
conditions:
- entity: switch.smart_switch_23022396705558510d0248e1e9bb85e5_outlet
state: 'off'
elements:
- type: state-icon
entity: switch.smart_switch_23022396705558510d0248e1e9bb85e5_outlet
style:
top: 78%
left: 96%
'--paper-item-icon-color': lightgrey
transform: translate(-50%, -50%) scale(0.6, 0.6)
- type: conditional
conditions:
- entity: switch.smart_switch_23022396705558510d0248e1e9bb85e5_outlet
state: 'on'
elements:
- type: state-icon
entity: switch.smart_switch_23022396705558510d0248e1e9bb85e5_outlet
style:
top: 78%
left: 96%
transform: translate(-50%, -50%) scale(0.6, 0.6)
animation: var(--state-animation-4)
- type: state-icon
entity: sensor.modbus_pe1_buffer_charge
style:
top: 27%
left: 64%
transform: translate(-50%,-50%) scale(0.8,0.8)
- type: state-icon
entity: sensor.buffer_pump_status
style:
top: 27%
left: 47%
'--paper-item-icon-color': var(--state-color-1)
animation: var(--state-animation-1)
transform: translate(-50%,-50%) scale(0.8,0.8)
- type: state-icon
entity: sensor.boiler_pump_status
style:
top: 85%
left: 79%
'--paper-item-icon-color': var(--state-color-2)
animation: var(--state-animation-2)
transform: translate(-50%,-50%) scale(0.8,0.8)
- type: state-label
entity: sensor.modbus_pe1_buffer_temperature_top
style:
top: 42%
left: 55%
opacity: 0
- type: state-label
entity: sensor.modbus_pe1_buffer_temperature_bottom
style:
top: 75%
left: 55%
opacity: 0
- type: state-label
entity: sensor.modbus_pe1_flow_temperature_actual
style:
top: 22%
left: 20%
opacity: 0
- type: custom:hui-element
card_type: gauge
name: ''
needle: true
min: 0
max: 70
segments:
- from: 0
color: steelblue
- from: 30
color: orange
- from: 40
color: orangered
- from: 55
color: red
entity: sensor.modbus_pe1_hotwater_temperature_top
style:
'--ha-card-background': rgba(1,1,1,0)
'--ha-card-border-width': 0
'--primary-text-color': black
border: none
top: 68%
left: 85%
width: 20%