automations.yaml

This commit is contained in:
Home Assistant Version Control committed 2026-10-14 17:28:43 +00:00
1 parent bac81fd7cd
commit 9dc8b9f5a4
1 file changed
+51 -24
+51 -24
View File
@@ -4776,11 +4776,12 @@
- id: '1791477238799' - id: '1791477238799'
alias: SparkX i7 - Filament sufficiency check at print start alias: SparkX i7 - Filament sufficiency check at print start
description: >- description: >-
When a print starts and stays printing for 45 s, compares the loaded CFS Lite When a print starts and stays printing for 45 s, reports how much filament the
spools against the slicer's filament requirement. A single-material job is job needs, how much has already been used and how much is left, then compares
checked exactly against its reported weight; a multi-material job has no the loaded CFS Lite spools against that. A single-colour job whose colour is in
per-colour figure, so each loaded spool is compared against the whole job a loaded slot is checked exactly against that slot's spool; otherwise the
total (worst case). Always sends a notification. slicer gives no per-colour figure, so each loaded spool is compared against the
whole job total. Always sends a notification.
triggers: triggers:
- trigger: state - trigger: state
entity_id: sensor.sparkx_i7_print_status entity_id: sensor.sparkx_i7_print_status
@@ -4793,49 +4794,75 @@
length_cm: "{{ states('sensor.sparkx_i7_expected_material_length') | float(0) }}" length_cm: "{{ states('sensor.sparkx_i7_expected_material_length') | float(0) }}"
weight_g: "{{ states('sensor.sparkx_i7_expected_material_weight') | float(0) }}" weight_g: "{{ states('sensor.sparkx_i7_expected_material_weight') | float(0) }}"
job_g: "{{ ((weight_g | float) if (weight_g | float) > 0 else (length_cm | float) * (gcm | float)) | round(1) }}" job_g: "{{ ((weight_g | float) if (weight_g | float) > 0 else (length_cm | float) * (gcm | float)) | round(1) }}"
gcol: "{{ state_attr('sensor.sparkx_i7_expected_material_length', 'color') | default('', true) | string | replace('#', '') | lower }}" used_len: "{{ states('sensor.sparkx_i7_used_material_length') | float(0) }}"
mono: "{{ (weight_g | float) > 0 and (gcol | length) <= 6 }}" used_g: "{{ (((used_len | float) * (gcm | float)) | round(1)) }}"
gcode_file: "{{ state_attr('sensor.sparkx_i7_expected_material_length', 'gcode_file') | default('', true) }}"
- variables: - variables:
report: |- report: |-
{% set ns = namespace(req=[], short=[], missing=[], loaded=[], avail=0) %}
{% set cols = namespace(list=[]) %} {% set cols = namespace(list=[]) %}
{% for n in ['1','2','3','4'] %}{% set cc = states('sensor.sparkx_i7_cfs_box_1_slot_' ~ n ~ '_color') | replace('#','') | lower %}{% if cc not in ['','none','unknown','unavailable'] %}{% set cols.list = cols.list + [cc] %}{% endif %}{% endfor %} {% for n in ['1','2','3','4'] %}{% set cc = states('sensor.sparkx_i7_cfs_box_1_slot_' ~ n ~ '_color') | replace('#','') | lower %}{% if cc not in ['','none','unknown','unavailable'] %}{% set cols.list = cols.list + [cc] %}{% endif %}{% endfor %}
{% set per_slot = gcol if (mono and gcol != '' and gcol in cols.list) else '' %} {% set gc = namespace(list=[]) %}
{% set mono_offline = mono and gcol != '' and gcol not in cols.list %} {% for p in (state_attr('sensor.sparkx_i7_expected_material_length','color') | default('', true) | string).split(';') %}{% set q = p | replace('#','') | lower | trim %}{% if q not in ['','none','unknown','unavailable'] %}{% set gc.list = gc.list + [q] %}{% endif %}{% endfor %}
{% set mc = namespace(list=[]) %}
{% for p in (state_attr('sensor.sparkx_i7_expected_material_length','material') | default('', true) | string).split(';') %}{% set q = p | trim %}{% if q not in ['','none','unknown','unavailable'] %}{% set mc.list = mc.list + [q] %}{% endif %}{% endfor %}
{% set single = (gc.list | length) == 1 %}
{% set gcol = gc.list[0] if single else '' %}
{% set rem_g = ([((job_g | float) - (used_g | float)), 0] | max) | round(1) %}
{% set ns = namespace(cover=[], below=[], short=[], ok=[], missing=[], loaded=[], match_label='', match_rem=0) %}
{% for n in ['1','2','3','4'] %} {% for n in ['1','2','3','4'] %}
{% set c = states('sensor.sparkx_i7_cfs_box_1_slot_' ~ n ~ '_color') | replace('#','') | lower %} {% set c = states('sensor.sparkx_i7_cfs_box_1_slot_' ~ n ~ '_color') | replace('#','') | lower %}
{% if c not in ['','none','unknown','unavailable'] %} {% if c not in ['','none','unknown','unavailable'] %}
{% set cname = states('sensor.sparkx_i7_slot_' ~ n ~ '_color_name') %} {% set cname = states('sensor.sparkx_i7_slot_' ~ n ~ '_color_name') %}
{% set flabel = states('sensor.sparkx_i7_cfs_box_1_slot_' ~ n ~ '_filament') %} {% set flabel = states('sensor.sparkx_i7_cfs_box_1_slot_' ~ n ~ '_filament') %}
{% set label = 'Slot ' ~ n ~ ' ' ~ (cname if cname not in ['','unknown','unavailable'] else (flabel if flabel not in ['','unknown','unavailable'] else ('#' ~ (c | upper)))) %} {% set label = 'Slot ' ~ n ~ ' ' ~ (cname if cname not in ['','unknown','unavailable'] else (flabel if flabel not in ['','unknown','unavailable'] else ('#' ~ (c | upper)))) %}
{% set sp = namespace(id='', rem=0) %} {% set sp = namespace(id='', rem=0, fw=0) %}
{% for e in integration_entities('spoolman') if e.endswith('_color_hex') %} {% for e in integration_entities('spoolman') if e.endswith('_color_hex') %}
{% if sp.id == '' and (states(e) | replace('#','') | lower) == c and (state_attr(e[:-10],'location') | default('', true) | lower) == 'cfs lite' %} {% if sp.id == '' and (states(e) | replace('#','') | lower) == c and (state_attr(e[:-10],'location') | default('', true) | lower) == 'cfs lite' %}
{% set sp.id = e[:-10] %} {% set sp.id = e[:-10] %}
{% set sp.rem = states(e[:-10]) | float(0) %} {% set sp.rem = states(e[:-10]) | float(0) %}
{% set sp.fw = state_attr(e[:-10],'filament_weight') | float(0) %}
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% if sp.id != '' %}{% set ns.avail = ns.avail + sp.rem %}{% set ns.loaded = ns.loaded + [label ~ ': ' ~ (sp.rem | round(1)) ~ ' g'] %}{% endif %} {% set pct = ((((sp.rem | float) / (sp.fw | float)) * 100) | round(0) | int) if (sp.fw | float) > 0 else 0 %}
{% if job_g > 0 %} {% if sp.id != '' %}{% set ns.loaded = ns.loaded + [label ~ ': ' ~ (sp.rem | round(1)) ~ ' g (' ~ pct ~ '%)'] %}{% endif %}
{% set req = job_g if (per_slot == '' or c == per_slot) else 0 %} {% if sp.id != '' and single and c == gcol %}{% set ns.match_label = label %}{% set ns.match_rem = sp.rem %}{% endif %}
{% if req > 0 %} {% if sp.id != '' %}
{% if sp.id == '' %}{% set ns.missing = ns.missing + [label ~ ' (#' ~ (c | upper) ~ ')'] %} {% if single and c == gcol %}
{% elif sp.rem < req %}{% set ns.short = ns.short + [label ~ ': ' ~ (sp.rem | round(1)) ~ ' g left, up to ' ~ req ~ ' g needed'] %} {% if (sp.rem | float) < (job_g | float) %}{% set ns.short = ns.short + [label ~ ': ' ~ (sp.rem | round(1)) ~ ' g (' ~ pct ~ '%) left, ' ~ job_g ~ ' g needed'] %}
{% else %}{% set ns.req = ns.req + [label ~ ': ' ~ (sp.rem | round(1)) ~ ' g left, up to ' ~ req ~ ' g needed'] %}{% endif %} {% else %}{% set ns.ok = ns.ok + [label ~ ': ' ~ (sp.rem | round(1)) ~ ' g (' ~ pct ~ '%) left, ' ~ job_g ~ ' g needed'] %}{% endif %}
{% elif single %}
{% if (sp.rem | float) >= (job_g | float) %}{% set ns.cover = ns.cover + [label ~ ': ' ~ (sp.rem | round(1)) ~ ' g (' ~ pct ~ '%)'] %}
{% else %}{% set ns.below = ns.below + [label ~ ': ' ~ (sp.rem | round(1)) ~ ' g (' ~ pct ~ '%)'] %}{% endif %}
{% else %}
{% if (sp.rem | float) < (job_g | float) %}{% set ns.short = ns.short + [label ~ ': ' ~ (sp.rem | round(1)) ~ ' g (' ~ pct ~ '%) left, up to ' ~ job_g ~ ' g needed'] %}
{% else %}{% set ns.ok = ns.ok + [label ~ ': ' ~ (sp.rem | round(1)) ~ ' g (' ~ pct ~ '%) left, up to ' ~ job_g ~ ' g needed'] %}{% endif %}
{% endif %} {% endif %}
{% elif job_g > 0 %}
{% set ns.missing = ns.missing + [label ~ ' (#' ~ (c | upper) ~ ')'] %}
{% endif %} {% endif %}
{% endif %} {% endif %}
{% endfor %} {% endfor %}
Job: {{ gcode_file if gcode_file not in ['','unknown','unavailable'] else (state_attr('sensor.sparkx_i7_print_status','file') | default('', true) | string).split('/')[-1] }}
Needs {{ job_g | round(1) }} g ({{ length_cm | round(1) }} cm) · used {{ used_g }} g · {{ rem_g }} g left to print
Slicer: {{ (mc.list | join(', ')) if mc.list else 'material unknown' }} · {{ ('single colour #' ~ (gcol | upper)) if single else ((gc.list | length) ~ ' colours') }}
{% if job_g <= 0 %}Cannot verify: slicer filament estimate not available yet.{% if ns.loaded %} Loaded: {{ ns.loaded | join('; ') }}.{% endif %} {% if job_g <= 0 %}Cannot verify: slicer filament estimate not available yet.{% if ns.loaded %} Loaded: {{ ns.loaded | join('; ') }}.{% endif %}
{% elif mono_offline %}Cannot verify: this looks like a single-colour print of #{{ gcol | upper }}, which is not in a loaded CFS slot. {% elif single and gcol in cols.list %}
{% if ns.short %}NOT ENOUGH filament:
{{ ns.short | join('\n') }}
{% elif ns.match_label %}Enough filament: {{ ns.match_label }}: {{ ns.match_rem | round(1) }} g left, {{ job_g }} g needed.
{% else %}Matched slot {{ gcol | upper }} has no Spoolman spool at CFS Lite, so remaining cannot be checked.{% endif %}
{% elif single %}No exact colour match for the print colour #{{ gcol | upper }} in a loaded CFS slot, so the exact spool cannot be identified.{% if ns.cover %}
Would cover {{ job_g }} g: {{ ns.cover | join('; ') }}{% endif %}{% if ns.below %}
Below {{ job_g }} g: {{ ns.below | join('; ') }}{% endif %}{% if not ns.cover and not ns.below %}
No loaded CFS slot has a matching Spoolman spool to compare.{% endif %}
{% elif ns.short %}NOT ENOUGH filament - possible shortfall: {% elif ns.short %}NOT ENOUGH filament - possible shortfall:
{{ ns.short | join('\n') }}{% if ns.req %} {{ ns.short | join('\n') }}{% if ns.ok %}
OK: {{ ns.req | join('; ') }}{% endif %}{% if ns.missing %} OK (would still cover the whole job): {{ ns.ok | join('; ') }}{% endif %}{% if ns.missing %}
No Spoolman spool matched for: {{ ns.missing | join(', ') }}{% endif %} No Spoolman spool matched for: {{ ns.missing | join(', ') }}{% endif %}
{% elif ns.req %}Enough filament: {% elif ns.ok %}Enough filament:
{{ ns.req | join('\n') }}{% if ns.missing %} {{ ns.ok | join('\n') }}{% if ns.missing %}
No Spoolman spool matched for: {{ ns.missing | join(', ') }}{% endif %} No Spoolman spool matched for: {{ ns.missing | join(', ') }}{% endif %}
{% else %}Cannot verify: could not match this job's filament to a loaded CFS slot.{% endif %} {% elif ns.missing %}Could not match any loaded CFS slot to a Spoolman spool.{% endif %}
- action: notify.persistent_notification - action: notify.persistent_notification
data: data:
title: Print started - filament check title: Print started - filament check