336 lines
14 KiB
YAML
336 lines
14 KiB
YAML
|
|
blueprint:
|
|||
|
|
name: Elegoo Printer Progress Notification (v4)
|
|||
|
|
description: Sends notifications for printer progress, status changes, and error
|
|||
|
|
states.
|
|||
|
|
author: Daniel Cherubini
|
|||
|
|
homeassistant:
|
|||
|
|
min_version: 2024.6.0
|
|||
|
|
domain: automation
|
|||
|
|
input:
|
|||
|
|
percent_complete_entity:
|
|||
|
|
name: Percent Complete Entity
|
|||
|
|
description: The percent complete sensor for the Elegoo printer (look for entities
|
|||
|
|
ending in '_percent_complete').
|
|||
|
|
selector:
|
|||
|
|
entity:
|
|||
|
|
domain:
|
|||
|
|
- sensor
|
|||
|
|
integration: elegoo_printer
|
|||
|
|
multiple: false
|
|||
|
|
reorder: false
|
|||
|
|
print_status_entity:
|
|||
|
|
name: Print Status Entity
|
|||
|
|
description: The print status sensor (should end with '_print_status').
|
|||
|
|
selector:
|
|||
|
|
entity:
|
|||
|
|
domain:
|
|||
|
|
- sensor
|
|||
|
|
integration: elegoo_printer
|
|||
|
|
device_class:
|
|||
|
|
- enum
|
|||
|
|
multiple: false
|
|||
|
|
reorder: false
|
|||
|
|
current_status_entity:
|
|||
|
|
name: Current Status Entity
|
|||
|
|
description: The current status sensor (should end with '_current_status').
|
|||
|
|
selector:
|
|||
|
|
entity:
|
|||
|
|
domain:
|
|||
|
|
- sensor
|
|||
|
|
integration: elegoo_printer
|
|||
|
|
device_class:
|
|||
|
|
- enum
|
|||
|
|
multiple: false
|
|||
|
|
reorder: false
|
|||
|
|
error_status_reason_entity:
|
|||
|
|
name: Error Status Reason Entity
|
|||
|
|
description: The error status reason sensor (should end with '_current_print_error_status_reason').
|
|||
|
|
selector:
|
|||
|
|
entity:
|
|||
|
|
domain:
|
|||
|
|
- sensor
|
|||
|
|
integration: elegoo_printer
|
|||
|
|
device_class:
|
|||
|
|
- enum
|
|||
|
|
multiple: false
|
|||
|
|
reorder: false
|
|||
|
|
notify_device:
|
|||
|
|
name: Notification Device
|
|||
|
|
description: The device to send notifications to.
|
|||
|
|
selector:
|
|||
|
|
device:
|
|||
|
|
integration: mobile_app
|
|||
|
|
multiple: false
|
|||
|
|
percentage_divisor:
|
|||
|
|
name: Notification Frequency
|
|||
|
|
description: Notify when the percentage complete is divisible by this number.
|
|||
|
|
Use 1 to be notified on every percentage change.
|
|||
|
|
selector:
|
|||
|
|
select:
|
|||
|
|
options:
|
|||
|
|
- '1'
|
|||
|
|
- '2'
|
|||
|
|
- '5'
|
|||
|
|
sort: false
|
|||
|
|
custom_value: false
|
|||
|
|
multiple: false
|
|||
|
|
default: '5'
|
|||
|
|
camera_entity:
|
|||
|
|
name: Printer Camera (Optional)
|
|||
|
|
description: Override the default camera entity for the printer. Leave blank
|
|||
|
|
to use the default camera from the printer device.
|
|||
|
|
default: ''
|
|||
|
|
selector:
|
|||
|
|
entity:
|
|||
|
|
domain:
|
|||
|
|
- camera
|
|||
|
|
multiple: false
|
|||
|
|
reorder: false
|
|||
|
|
dashboard_url:
|
|||
|
|
name: Dashboard URL (Optional)
|
|||
|
|
description: The path to open when the notification is clicked (e.g., '/dashboard-example/example',
|
|||
|
|
not the full URL).
|
|||
|
|
default: ''
|
|||
|
|
enable_status_notifications:
|
|||
|
|
name: Enable Status Change Notifications
|
|||
|
|
description: Send notifications when printer status changes (e.g., homing, heating,
|
|||
|
|
etc.)
|
|||
|
|
default: true
|
|||
|
|
selector:
|
|||
|
|
boolean: {}
|
|||
|
|
source_url: https://github.com/danielcherubini/elegoo-homeassistant/blob/main/blueprints/automation/elegoo_printer/elegoo_printer_progress.yaml
|
|||
|
|
mode: single
|
|||
|
|
max_exceeded: silent
|
|||
|
|
variables:
|
|||
|
|
percent_complete_entity: !input percent_complete_entity
|
|||
|
|
notify_device: !input notify_device
|
|||
|
|
percentage_divisor: !input percentage_divisor
|
|||
|
|
camera_entity_input: !input camera_entity
|
|||
|
|
dashboard_url: !input dashboard_url
|
|||
|
|
enable_status_notifications: !input enable_status_notifications
|
|||
|
|
print_status_entity: !input print_status_entity
|
|||
|
|
current_status_entity: !input current_status_entity
|
|||
|
|
error_status_reason_entity: !input error_status_reason_entity
|
|||
|
|
printer_device: '{{ device_id(percent_complete_entity) }}'
|
|||
|
|
notification_group: '{{ device_attr(printer_device, ''name'') | slugify }}'
|
|||
|
|
end_time_entity: '{{ device_entities(printer_device) | select(''search'', ''_end_time'')
|
|||
|
|
| first }}'
|
|||
|
|
file_name_entity: '{{ device_entities(printer_device) | select(''search'', ''_file_name'')
|
|||
|
|
| first }}'
|
|||
|
|
current_layer_entity: '{{ device_entities(printer_device) | select(''search'', ''_current_layer'')
|
|||
|
|
| first }}'
|
|||
|
|
total_layers_entity: '{{ device_entities(printer_device) | select(''search'', ''_total_layers'')
|
|||
|
|
| first }}'
|
|||
|
|
camera_entity: "{{ (camera_entity_input\n if camera_entity_input != ''\n else
|
|||
|
|
(device_entities(printer_device) | select('match', '^camera\\.') | first))\n |
|
|||
|
|
default('', true) }}"
|
|||
|
|
trigger:
|
|||
|
|
- platform: state
|
|||
|
|
entity_id: !input percent_complete_entity
|
|||
|
|
- platform: state
|
|||
|
|
entity_id: !input print_status_entity
|
|||
|
|
- platform: state
|
|||
|
|
entity_id: !input current_status_entity
|
|||
|
|
- platform: state
|
|||
|
|
entity_id: !input error_status_reason_entity
|
|||
|
|
condition: []
|
|||
|
|
action:
|
|||
|
|
- choose:
|
|||
|
|
- conditions:
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ trigger.entity_id == percent_complete_entity }}'
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ states(percent_complete_entity) not in [''unknown'', ''unavailable'']
|
|||
|
|
}}'
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ states(percent_complete_entity) | int(0) < 100 }}'
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ states(percent_complete_entity) | int(0) % (percentage_divisor
|
|||
|
|
| int) == 0 }}'
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ current_status_entity != none and states(current_status_entity)
|
|||
|
|
== ''printing'' }}'
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ notify_device != '''' }}'
|
|||
|
|
sequence:
|
|||
|
|
- device_id: !input notify_device
|
|||
|
|
domain: mobile_app
|
|||
|
|
type: notify
|
|||
|
|
title: 'Printing: {{ states(percent_complete_entity) | int(0) }}%
|
|||
|
|
|
|||
|
|
Layer: {{ (states(current_layer_entity)|default(''?'', true)) }}/{{ (states(total_layers_entity)|default(''?'',
|
|||
|
|
true)) }}'
|
|||
|
|
message: '{{ states(file_name_entity)|default(''Unknown file'', true) }}'
|
|||
|
|
data:
|
|||
|
|
chronometer: true
|
|||
|
|
when: '{{ as_timestamp(states(end_time_entity))|int if end_time_entity !=
|
|||
|
|
none and states(end_time_entity) not in [''unknown'', ''unavailable''] else
|
|||
|
|
0 }}'
|
|||
|
|
progress: '{{ states(percent_complete_entity)|int(0) }}'
|
|||
|
|
progress_max: 100
|
|||
|
|
image: '{{ (''/api/camera_proxy/'' ~ camera_entity) if (camera_entity|default('''',
|
|||
|
|
true)) != '''' else '''' }}'
|
|||
|
|
url: '{{ dashboard_url }}'
|
|||
|
|
clickAction: '{{ dashboard_url }}'
|
|||
|
|
group: '{{ notification_group }}'
|
|||
|
|
channel: '{{ notification_group }}'
|
|||
|
|
tag: '{{ notification_group }}'
|
|||
|
|
alert_once: true
|
|||
|
|
sticky: true
|
|||
|
|
push:
|
|||
|
|
interruption-level: passive
|
|||
|
|
- conditions:
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ notify_device != '''' }}'
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ states(print_status_entity) == ''complete'' }}'
|
|||
|
|
- condition: or
|
|||
|
|
conditions:
|
|||
|
|
- condition: and
|
|||
|
|
conditions:
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ trigger.entity_id == print_status_entity }}'
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ trigger.from_state.state != ''complete'' }}'
|
|||
|
|
- condition: and
|
|||
|
|
conditions:
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ trigger.entity_id == percent_complete_entity }}'
|
|||
|
|
sequence:
|
|||
|
|
- device_id: !input notify_device
|
|||
|
|
domain: mobile_app
|
|||
|
|
type: notify
|
|||
|
|
title: "\U0001F389 Print Complete!"
|
|||
|
|
message: Print has finished successfully
|
|||
|
|
data:
|
|||
|
|
image: '{{ (''/api/camera_proxy/'' ~ camera_entity) if (camera_entity|default('''',
|
|||
|
|
true)) != '''' else '''' }}'
|
|||
|
|
url: '{{ dashboard_url }}'
|
|||
|
|
clickAction: '{{ dashboard_url }}'
|
|||
|
|
group: '{{ notification_group }}'
|
|||
|
|
channel: '{{ notification_group }}'
|
|||
|
|
tag: '{{ notification_group }}'
|
|||
|
|
sticky: true
|
|||
|
|
alert_once: true
|
|||
|
|
push:
|
|||
|
|
interruption-level: time-sensitive
|
|||
|
|
- conditions:
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ trigger.entity_id == print_status_entity }}'
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ notify_device != '''' }}'
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ enable_status_notifications }}'
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ states(print_status_entity) not in [''complete'', ''stopped'',
|
|||
|
|
''stopping'', ''idle'', ''unknown'', ''unavailable''] }}'
|
|||
|
|
sequence:
|
|||
|
|
- device_id: !input notify_device
|
|||
|
|
domain: mobile_app
|
|||
|
|
type: notify
|
|||
|
|
title: Printer Status Update
|
|||
|
|
message: "{% set status = states(print_status_entity) %} {% set file_name =
|
|||
|
|
states(file_name_entity)|default('Unknown file', true) %} {% if status ==
|
|||
|
|
'homing' %}\n \U0001F3E0 Printer is homing\n{% elif status == 'printing'
|
|||
|
|
%}\n \U0001F5A8️ Started printing: {{ file_name }}\n{% elif status == 'paused'
|
|||
|
|
or status == 'pausing' %}\n ⏸️ Print paused: {{ file_name }}\n{% elif status
|
|||
|
|
== 'loading' %}\n \U0001F4E5 Loading filament\n{% elif status == 'dropping'
|
|||
|
|
%}\n \U0001F53D Platform dropping\n{% elif status == 'lifting' %}\n \U0001F53C
|
|||
|
|
Platform lifting\n{% elif status == 'file_checking' %}\n \U0001F4C1 Checking
|
|||
|
|
print file\n{% elif status == 'recovery' or status == 'printing_recovery'
|
|||
|
|
%}\n \U0001F504 Print recovery in progress\n{% elif status == 'preheating'
|
|||
|
|
%}\n \U0001F525 Preheating for print\n{% elif status == 'leveling' %}\n \U0001F4D0
|
|||
|
|
Bed leveling in progress\n{% else %}\n \U0001F4CA Status: {{ status }}\n{%
|
|||
|
|
endif %}"
|
|||
|
|
data:
|
|||
|
|
url: '{{ dashboard_url }}'
|
|||
|
|
clickAction: '{{ dashboard_url }}'
|
|||
|
|
group: '{{ notification_group }}'
|
|||
|
|
channel: '{{ notification_group }}'
|
|||
|
|
tag: '{{ notification_group }}_status'
|
|||
|
|
alert_once: true
|
|||
|
|
push:
|
|||
|
|
interruption-level: passive
|
|||
|
|
- conditions:
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ trigger.entity_id == current_status_entity }}'
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ notify_device != '''' }}'
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ enable_status_notifications }}'
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ states(current_status_entity) not in [''idle'', ''printing'',
|
|||
|
|
''unknown'', ''unavailable''] }}'
|
|||
|
|
sequence:
|
|||
|
|
- device_id: !input notify_device
|
|||
|
|
domain: mobile_app
|
|||
|
|
type: notify
|
|||
|
|
title: Machine Status Update
|
|||
|
|
message: "{% set status = states(current_status_entity) %} {% set file_name
|
|||
|
|
= states(file_name_entity)|default('Unknown file', true) %} {% if status ==
|
|||
|
|
'file_transferring' %}\n \U0001F4C1 File transfer in progress\n{% elif status
|
|||
|
|
== 'exposure_testing' %}\n \U0001F52C Exposure test running\n{% elif status
|
|||
|
|
== 'devices_testing' %}\n \U0001F527 Device self-check running\n{% elif status
|
|||
|
|
== 'leveling' %}\n \U0001F4D0 Bed leveling in progress\n{% elif status ==
|
|||
|
|
'loading_unloading' %}\n \U0001F4E5\U0001F4E4 Loading/unloading filament\n{%
|
|||
|
|
else %}\n \U0001F4CA Machine status: {{ status }}\n{% endif %}"
|
|||
|
|
data:
|
|||
|
|
url: '{{ dashboard_url }}'
|
|||
|
|
clickAction: '{{ dashboard_url }}'
|
|||
|
|
group: '{{ notification_group }}'
|
|||
|
|
channel: '{{ notification_group }}'
|
|||
|
|
tag: '{{ notification_group }}_machine_status'
|
|||
|
|
alert_once: true
|
|||
|
|
push:
|
|||
|
|
interruption-level: passive
|
|||
|
|
- conditions:
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ trigger.entity_id == error_status_reason_entity }}'
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ notify_device != '''' }}'
|
|||
|
|
- condition: template
|
|||
|
|
value_template: '{{ states(error_status_reason_entity) not in [''ok'', ''none'',
|
|||
|
|
''unknown'', ''unavailable''] }}'
|
|||
|
|
sequence:
|
|||
|
|
- device_id: !input notify_device
|
|||
|
|
domain: mobile_app
|
|||
|
|
type: notify
|
|||
|
|
title: "\U0001F6A8 Critical Printer Error!"
|
|||
|
|
message: "{% set error = states(error_status_reason_entity) %} {% set file_name
|
|||
|
|
= states(file_name_entity)|default('current print', true) %} {% if error ==
|
|||
|
|
'filament_runout' %}\n \U0001F9F5 Filament runout detected during {{ file_name
|
|||
|
|
}}! Please load new filament.\n{% elif error == 'filament_about_to_runout'
|
|||
|
|
%}\n ⚠️ Filament runout imminent for {{ file_name }}! Please prepare new
|
|||
|
|
filament.\n{% elif error == 'filament_jam' %}\n \U0001F6AB Filament jam detected
|
|||
|
|
during {{ file_name }}! Please check the extruder.\n{% elif error == 'temp_error'
|
|||
|
|
%}\n \U0001F321️ Temperature error detected! Please check nozzle and bed
|
|||
|
|
temperatures.\n{% elif error == 'level_failed' %}\n \U0001F4D0 Bed leveling
|
|||
|
|
failed! Please check the bed leveling system.\n{% elif error == 'home_failed'
|
|||
|
|
or error == 'home_failed_x' or error == 'home_failed_y' or error == 'home_failed_z'
|
|||
|
|
%}\n \U0001F3E0 Homing failed! Please check the printer axes and endstops.\n{%
|
|||
|
|
elif error == 'bed_adhesion_failed' %}\n \U0001F6CF️ Print detached from
|
|||
|
|
bed during {{ file_name }}!\n{% elif error == 'move_abnormal' %}\n ⚙️ Motor
|
|||
|
|
movement abnormality detected!\n{% elif error == 'file_error' %}\n \U0001F4C1
|
|||
|
|
Print file error during {{ file_name }}!\n{% elif error == 'udisk_remove'
|
|||
|
|
%}\n \U0001F4BE USB drive was removed during printing!\n{% elif error ==
|
|||
|
|
'nozzle_temp_sensor_offline' %}\n \U0001F321️ Nozzle temperature sensor is
|
|||
|
|
offline!\n{% elif error == 'bed_temp_sensor_offline' %}\n \U0001F321️ Bed
|
|||
|
|
temperature sensor is offline!\n{% elif error == 'camera_error' %}\n \U0001F4F7
|
|||
|
|
Camera connection error!\n{% elif error == 'network_error' %}\n \U0001F310
|
|||
|
|
Network connection error!\n{% elif error == 'server_connect_failed' %}\n \U0001F5A5️
|
|||
|
|
Server connection failed!\n{% elif error == 'disconnect_app' %}\n \U0001F4F1
|
|||
|
|
Controlling app disconnected during print!\n{% else %}\n ⚠️ Error: {{ error
|
|||
|
|
}}\n{% endif %}"
|
|||
|
|
data:
|
|||
|
|
image: '{{ (''/api/camera_proxy/'' ~ camera_entity) if (camera_entity|default('''',
|
|||
|
|
true)) != '''' else '''' }}'
|
|||
|
|
url: '{{ dashboard_url }}'
|
|||
|
|
clickAction: '{{ dashboard_url }}'
|
|||
|
|
group: '{{ notification_group }}'
|
|||
|
|
channel: '{{ notification_group }}'
|
|||
|
|
tag: '{{ notification_group }}_critical_error'
|
|||
|
|
sticky: true
|
|||
|
|
alert_once: false
|
|||
|
|
push:
|
|||
|
|
interruption-level: time-sensitive
|