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