This commit is contained in:
Home Assistant Version Control
2026-10-15 13:24:00 +00:00
parent c85606c96e
commit 90d32d5573
6 changed files with 368 additions and 31 deletions
@@ -0,0 +1,152 @@
# ha_mcp_backup
schema_version: 1
domain: automation
entity_id: '1791477238762'
captured: '2026-10-15T13:23:53.053853+00:00'
tool: ha_config_set_automation
config:
id: '1791477238762'
alias: SparkX i7 - Latch print spool for Spoolman
description: 'Segment tracking for Spoolman: at print start resets the length checkpoint
and per-slot gram counters and latches the active CFS slot. On every slot change
mid-print, deducts the exact extrusion of the finished segment (used_material_length
delta x g/cm) from the Spoolman spool in the CFS Lite location matching the previous
slot color hex (only if that spool has remaining weight), accumulates grams per
slot, notifies on no-match, then re-baselines the checkpoint and advances the
latch.'
triggers:
- trigger: state
entity_id: sensor.sparkx_i7_print_status
to: printing
id: print_started
- trigger: state
entity_id: sensor.sparkx_i7_active_filament_slot
id: slot_changed
conditions:
- condition: state
entity_id: sensor.sparkx_i7_print_status
state: printing
actions:
- variables:
new_slot: '{{ states(''sensor.sparkx_i7_active_filament_slot'') }}'
old_slot: '{{ states(''input_text.sparkx_i7_print_spool_latch'') }}'
cur: '{{ states(''sensor.sparkx_i7_used_material_length'') | float(0) }}'
- choose:
- conditions:
condition: trigger
id: print_started
sequence:
- action: input_number.set_value
target:
entity_id: input_number.sparkx_i7_spoolman_length_checkpoint
data:
value: '{{ cur }}'
- action: input_number.set_value
target:
entity_id:
- input_number.sparkx_i7_slot_1_grams
- input_number.sparkx_i7_slot_2_grams
- input_number.sparkx_i7_slot_3_grams
- input_number.sparkx_i7_slot_4_grams
data:
value: 0
- action: input_text.set_value
target:
entity_id: input_text.sparkx_i7_print_spool_latch
data:
value: '{{ new_slot if new_slot not in [''unknown'', ''unavailable''] else
'''' }}'
- conditions:
condition: template
value_template: '{{ old_slot not in ['''', ''unknown'', ''unavailable''] and
new_slot not in ['''', ''unknown'', ''unavailable''] and new_slot != old_slot
}}'
sequence:
- variables:
grams: '{{ (([cur | float - (states(''input_number.sparkx_i7_spoolman_length_checkpoint'')
| float(0)), 0] | max) * (states(''input_number.sparkx_i7_filament_g_cm'')
| float(0.03))) | round(2) }}'
color: '{{ states(''sensor.sparkx_i7_cfs_'' ~ (old_slot | lower | replace(''
'', ''_'')) ~ ''_color'') | replace(''#'', '''') | lower }}'
- variables:
spool_id: '{% set ns = namespace(id='''') %}{% for e in integration_entities(''spoolman'')
%}{% if e.endswith(''_color_hex'') and (state_attr(e[:-10], ''location'')
| default('''', true) | lower) == (''cfs lite '' ~ old_slot.split(''_'')[-1])
%}{% set b = e[:-10] %}{% if (states(b) | float(0)) > 0 and ns.id == ''''
%}{% set ns.id = states(b ~ ''_id'') %}{% endif %}{% endif %}{% endfor
%}{{ ns.id }}'
- if:
condition: template
value_template: '{{ grams | float > 0 }}'
then:
- choose:
- conditions:
condition: template
value_template: '{{ spool_id not in ['''', ''unknown'', ''unavailable'']
}}'
sequence:
- action: spoolman.use_spool_filament
data:
id: '{{ spool_id | int(0) }}'
use_weight: '{{ grams | float(0) }}'
- if:
condition: template
value_template: '{{ old_slot.split(''_'')[-1] in [''1'', ''2'', ''3'',
''4''] }}'
then:
- action: input_number.set_value
target:
entity_id: input_number.sparkx_i7_slot_{{ old_slot.split('_')[-1]
}}_grams
data:
value: '{{ (states(''input_number.sparkx_i7_slot_'' ~ old_slot.split(''_'')[-1]
~ ''_grams'') | float(0)) + (grams | float) }}'
default:
- action: notify.persistent_notification
data:
title: 'Spoolman: no spool for slot color'
message: 'Segment of {{ grams }} g from {{ old_slot }} (color #{{ color
| upper }}) could not be deducted - no Spoolman spool in the CFS Lite
location with remaining weight matches that color. Register the new
roll in Spoolman with location CFS Lite, then adjust manually if needed.'
- action: notify.mobile_app_francos_ipad
data:
title: 'Spoolman: no spool for slot color'
message: 'Segment of {{ grams }} g from {{ old_slot }} (color #{{ color
| upper }}) could not be deducted - no Spoolman spool in the CFS Lite
location with remaining weight matches that color. Register the new
roll in Spoolman with location CFS Lite, then adjust manually if needed.'
- action: notify.mobile_app_sm_f956w
data:
title: 'Spoolman: no spool for slot color'
message: 'Segment of {{ grams }} g from {{ old_slot }} (color #{{ color
| upper }}) could not be deducted - no Spoolman spool in the CFS Lite
location with remaining weight matches that color. Register the new
roll in Spoolman with location CFS Lite, then adjust manually if needed.'
- action: input_number.set_value
target:
entity_id: input_number.sparkx_i7_spoolman_length_checkpoint
data:
value: '{{ cur }}'
- action: input_text.set_value
target:
entity_id: input_text.sparkx_i7_print_spool_latch
data:
value: '{{ new_slot }}'
- conditions:
condition: template
value_template: '{{ old_slot in ['''', ''unknown'', ''unavailable''] and new_slot
not in ['''', ''unknown'', ''unavailable''] }}'
sequence:
- action: input_number.set_value
target:
entity_id: input_number.sparkx_i7_spoolman_length_checkpoint
data:
value: '{{ cur }}'
- action: input_text.set_value
target:
entity_id: input_text.sparkx_i7_print_spool_latch
data:
value: '{{ new_slot }}'
mode: queued
max: 10
@@ -0,0 +1,122 @@
# ha_mcp_backup
schema_version: 1
domain: automation
entity_id: '1791477238799'
captured: '2026-10-15T13:23:53.149869+00:00'
tool: ha_config_set_automation
config:
id: '1791477238799'
alias: SparkX i7 - Filament sufficiency check at print start
description: When a print starts and stays printing for 45 s, reports how much filament
the job needs, how much has already been used and how much is left, then compares
the loaded CFS Lite spools against that. A single-colour job whose colour is in
a loaded slot is checked exactly against that slot's spool; otherwise the slicer
gives no per-colour figure, so each loaded spool is compared against the whole
job total. Always sends a notification.
triggers:
- trigger: state
entity_id: sensor.sparkx_i7_print_status
to: printing
for: 00:00:45
conditions: []
actions:
- variables:
gcm: '{{ states(''input_number.sparkx_i7_filament_g_cm'') | float(0.0298) }}'
length_cm: '{{ states(''sensor.sparkx_i7_expected_material_length'') | 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) }}'
used_len: '{{ states(''sensor.sparkx_i7_used_material_length'') | float(0) }}'
used_g: '{{ (((used_len | float) * (gcm | float)) | round(1)) }}'
gcode_file: '{{ state_attr(''sensor.sparkx_i7_expected_material_length'', ''gcode_file'')
| default('''', true) }}'
- variables:
report: "{% set cols = namespace(list=[]) %}\n{% 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 %}\n{% set\
\ gc = namespace(list=[]) %}\n{% 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 %}\n{% set mc = namespace(list=[])\
\ %}\n{% 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 %}\n{% set single = (gc.list | length) == 1 %}\n\
{% set gcol = gc.list[0] if single else '' %}\n{% set aslot = (states('sensor.sparkx_i7_active_filament_slot')\
\ | default('', true) | string).split('_')[-1] %}\n{% set aslot = aslot if\
\ aslot in ['1','2','3','4'] else '' %}\n{% set rem_g = ([((job_g | float)\
\ - (used_g | float)), 0] | max) | round(1) %}\n{% set ns = namespace(cover=[],\
\ below=[], short=[], ok=[], missing=[], loaded=[], match_label='', match_rem=0)\
\ %}\n{% for n in ['1','2','3','4'] %}\n{% set c = states('sensor.sparkx_i7_cfs_box_1_slot_'\
\ ~ n ~ '_color') | replace('#','') | lower %}\n{% if c not in ['','none','unknown','unavailable']\
\ %}\n{% set cname = states('sensor.sparkx_i7_slot_' ~ n ~ '_color_name')\
\ %}\n{% set flabel = states('sensor.sparkx_i7_cfs_box_1_slot_' ~ n ~ '_filament')\
\ %}\n{% set label = 'Slot ' ~ n ~ ' ' ~ (cname if cname not in ['','unknown','unavailable']\
\ else (flabel if flabel not in ['','unknown','unavailable'] else ('#' ~ (c\
\ | upper)))) %}\n{% set sp = namespace(id='', rem=0, fw=0) %}\n{% for e in\
\ integration_entities('spoolman') if e.endswith('_color_hex') %}\n{% if sp.id\
\ == '' and (state_attr(e[:-10],'location') | default('', true) | lower) ==\
\ ('cfs lite ' ~ n) %}\n{% set sp.id = e[:-10] %}\n{% set sp.rem = states(e[:-10])\
\ | float(0) %}\n{% set sp.fw = state_attr(e[:-10],'filament_weight') | float(0)\
\ %}\n{% endif %}\n{% endfor %}\n{% set pct = ((((sp.rem | float) / (sp.fw\
\ | float)) * 100) | round(0) | int) if (sp.fw | float) > 0 else 0 %}\n{%\
\ if sp.id != '' %}{% set ns.loaded = ns.loaded + [label ~ ': ' ~ (sp.rem\
\ | round(1)) ~ ' g (' ~ pct ~ '%)'] %}{% endif %}\n{% if sp.id != '' and\
\ single and n == aslot %}{% set ns.match_label = label %}{% set ns.match_rem\
\ = sp.rem %}{% endif %}\n{% if sp.id != '' %}\n{% if single and n == aslot\
\ %}\n{% if (sp.rem | float) < (job_g | float) %}{% set ns.short = ns.short\
\ + [label ~ ': ' ~ (sp.rem | round(1)) ~ ' g (' ~ pct ~ '%) left, ' ~ job_g\
\ ~ ' g needed'] %}\n{% else %}{% set ns.ok = ns.ok + [label ~ ': ' ~ (sp.rem\
\ | round(1)) ~ ' g (' ~ pct ~ '%) left, ' ~ job_g ~ ' g needed'] %}{% endif\
\ %}\n{% elif single %}\n{% if (sp.rem | float) >= (job_g | float) %}{% set\
\ ns.cover = ns.cover + [label ~ ': ' ~ (sp.rem | round(1)) ~ ' g (' ~ pct\
\ ~ '%)'] %}\n{% else %}{% set ns.below = ns.below + [label ~ ': ' ~ (sp.rem\
\ | round(1)) ~ ' g (' ~ pct ~ '%)'] %}{% endif %}\n{% else %}\n{% 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']\
\ %}\n{% else %}{% set ns.ok = ns.ok + [label ~ ': ' ~ (sp.rem | round(1))\
\ ~ ' g (' ~ pct ~ '%) left, up to ' ~ job_g ~ ' g needed'] %}{% endif %}\n\
{% endif %}\n{% elif job_g > 0 %}\n{% set ns.missing = ns.missing + [label\
\ ~ ' (#' ~ (c | upper) ~ ')'] %}\n{% endif %}\n{% endif %}\n{% endfor %}\n\
Job: {{ gcode_file if gcode_file not in ['','unknown','unavailable'] else\
\ (state_attr('sensor.sparkx_i7_print_status','file') | default('', true)\
\ | string).split('/')[-1] }}\nNeeds {{ job_g | round(1) }} g ({{ length_cm\
\ | round(1) }} cm) \xB7 used {{ used_g }} g \xB7 {{ rem_g }} g left to print\n\
Slicer: {{ (mc.list | join(', ')) if mc.list else 'material unknown' }} \xB7\
\ {{ ('single colour #' ~ (gcol | upper)) if single else ((gc.list | length)\
\ ~ ' colours') }}\n{% if job_g <= 0 %}Cannot verify: slicer filament estimate\
\ not available yet.{% if ns.loaded %}\nLoaded:\n- {{ ns.loaded | join('\\\
n- ') }}{% endif %}\n{% elif single and aslot != '' %}\n{% if ns.short %}NOT\
\ ENOUGH filament:\n- {{ ns.short | join('\\n- ') }}\n{% elif ns.match_label\
\ %}Enough filament: {{ ns.match_label }}: {{ ns.match_rem | round(1) }} g\
\ left, {{ job_g }} g needed.\n{% else %}Active slot {{ aslot }} has no Spoolman\
\ spool at CFS Lite, so remaining cannot be checked.{% endif %}\n{% 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 %}\nWould\
\ cover {{ job_g }} g:\n- {{ ns.cover | join('\\n- ') }}{% endif %}{% if ns.below\
\ %}\nBelow {{ job_g }} g:\n- {{ ns.below | join('\\n- ') }}{% endif %}{%\
\ if not ns.cover and not ns.below %}\nNo loaded CFS slot has a matching Spoolman\
\ spool to compare.{% endif %}\n{% elif ns.short %}NOT ENOUGH filament - possible\
\ shortfall:\n- {{ ns.short | join('\\n- ') }}{% if ns.ok %}\nOK (would still\
\ cover the whole job):\n- {{ ns.ok | join('\\n- ') }}{% endif %}{% if ns.missing\
\ %}\nNo Spoolman spool matched for:\n- {{ ns.missing | join('\\n- ') }}{%\
\ endif %}\n{% elif ns.ok %}Enough filament:\n- {{ ns.ok | join('\\n- ') }}{%\
\ if ns.missing %}\nNo Spoolman spool matched for:\n- {{ ns.missing | join('\\\
n- ') }}{% endif %}\n{% elif ns.missing %}Could not match any loaded CFS slot\
\ to a Spoolman spool.{% endif %}"
- action: notify.persistent_notification
data:
title: Print started - filament check
message: '{{ report }}'
- action: notify.mobile_app_francos_ipad
data:
title: Print started - filament check
message: '{{ report }}'
- action: notify.mobile_app_sm_f956w
data:
title: Print started - filament check
message: '{{ report }}'
mode: single
@@ -0,0 +1,60 @@
# ha_mcp_backup
schema_version: 1
domain: script
entity_id: spoolman_set_spool_remaining
captured: '2026-10-15T13:23:53.118614+00:00'
tool: ha_config_set_script
config:
alias: Spoolman - Set Spool Remaining
fields:
slot:
name: CFS Slot
description: CFS slot number 1-4 - resolves the spool by the slot color hex
selector:
number:
min: 1
max: 4
mode: box
spool_id:
name: Spool ID
description: Direct Spoolman spool ID - used when no slot is given
selector:
number:
min: 1
max: 9999
mode: box
sequence:
- variables:
resolved_id: '{% set n = (slot | int(0)) if slot is defined else 0 %}{% if n
>= 1 %}{% set ns = namespace(id='''') %}{% for e in integration_entities(''spoolman'')
%}{% if e.endswith(''_color_hex'') and (state_attr(e[:-10], ''location'')
| default('''', true) | lower) == (''cfs lite '' ~ (n | int)) and ns.id ==
'''' %}{% set ns.id = states(e[:-10] ~ ''_id'') %}{% endif %}{% endfor %}{{
ns.id }}{% else %}{{ (spool_id | int(0)) if spool_id is defined else 0 }}{%
endif %}'
slot_n: '{{ (slot | int(0)) if slot is defined else 0 }}'
- choose:
- conditions:
condition: template
value_template: '{{ resolved_id | int(0) > 0 }}'
sequence:
- action: spoolman.patch_spool
data:
id: '{{ resolved_id | int(0) }}'
remaining_weight: '{{ states(''input_number.spoolman_set_remaining'') |
float(0) }}'
default:
- action: notify.persistent_notification
data:
title: Spoolman - remaining not set
message: '{% if slot_n | int >= 1 %}No Spoolman spool matched CFS slot {{
slot_n }} (color {{ states(''sensor.sparkx_i7_cfs_box_1_slot_'' ~ (slot_n
| int) ~ ''_color'') }}) in the CFS Lite location - register a spool with
that color hex and location in Spoolman, then try again.{% else %}No spool
resolved - pass spool_id or a CFS slot 1-4. Nothing was set.{% endif %}'
mode: single
description: Sets a Spoolman spool remaining weight from the shared helper input_number.spoolman_set_remaining.
Pass slot (1-4) to resolve the spool by the CFS slot color hex in the CFS Lite
location (no remaining-weight guard, so an exhausted spool can be reset to full),
or pass spool_id directly. Notifies via persistent notification when nothing could
be resolved.
+3
View File
@@ -4564,3 +4564,6 @@
{"timestamp": "2026-10-15T13:22:39.822007+00:00", "tool_name": "ha_config_get_automation", "parameters": {"identifier": "1791477238762"}, "execution_time_ms": 334.63048934936523, "success": true, "error_message": null, "response_size_bytes": 5649, "user_context": null}
{"timestamp": "2026-10-15T13:22:39.905414+00:00", "tool_name": "ha_config_get_automation", "parameters": {"identifier": "1791477238799"}, "execution_time_ms": 413.3596420288086, "success": true, "error_message": null, "response_size_bytes": 7574, "user_context": null}
{"timestamp": "2026-10-15T13:23:18.159012+00:00", "tool_name": "ha_config_set_automation", "parameters": {"config": null, "identifier": "1791477238729", "python_transform": "_repl = [(\"matching the latched slot color\", \"matching the latched slot's CFS Lite location\"), (\"Spoolman: no spool for slot color\", \"Spoolman: no spool for the latched slot\"), (\"no Spoolman spool in the CFS Lite location with remaining weight matches that color. Register the new roll in Spoolman with location CFS Lite, then adjust manually if needed.\", \"no Spoolman spool with remaining weight is in that slot's CFS Lite location. Register the new roll in Spoolman in that location, then adjust manually if needed.\")]\nstack = [config]\nfor _ in range(20000):\n if not stack:\n break\n node = stack.pop()\n if isinstance(node, dict):\n for k in list(node.keys()):\n v = node[k]\n if isinstance(v, str):\n for a, b in _repl:\n if a in v:\n v = v.replace(a, b)\n node[k] = v\n elif isinstance(v, (dict, list)):\n stack.append(v)\n elif isinstance(node, list):\n for i in range(len(node)):\n v = node[i]\n if isinstance(v, str):\n for a, b in _repl:\n if a in v:\n v = v.replace(a, b)\n node[i] = v\n elif isinstance(v, (dict, list)):\n stack.append(v)", "config_hash": "75d85b947ad8ec44", "take_control_of_blueprint": false, "category": null, "wait": true, "enabled": null, "run_actions": false, "MandatoryBPS": true, "BestPracticeKey": null}, "execution_time_ms": 622.8833198547363, "success": true, "error_message": null, "response_size_bytes": 83935, "user_context": null}
{"timestamp": "2026-10-15T13:23:54.686981+00:00", "tool_name": "ha_config_set_automation", "parameters": {"config": null, "identifier": "1791477238762", "python_transform": "_repl = [(\"matching the previous slot color hex\", \"matching the previous slot's CFS Lite location\"), (\"Spoolman: no spool for slot color\", \"Spoolman: no spool for the latched slot\"), (\"no Spoolman spool in the CFS Lite location with remaining weight matches that color. Register the new roll in Spoolman with location CFS Lite, then adjust manually if needed.\", \"no Spoolman spool with remaining weight is in that slot's CFS Lite location. Register the new roll in Spoolman in that location, then adjust manually if needed.\")]\nstack = [config]\nfor _ in range(20000):\n if not stack:\n break\n node = stack.pop()\n if isinstance(node, dict):\n for k in list(node.keys()):\n v = node[k]\n if isinstance(v, str):\n for a, b in _repl:\n if a in v:\n v = v.replace(a, b)\n node[k] = v\n elif isinstance(v, (dict, list)):\n stack.append(v)\n elif isinstance(node, list):\n for i in range(len(node)):\n v = node[i]\n if isinstance(v, str):\n for a, b in _repl:\n if a in v:\n v = v.replace(a, b)\n node[i] = v\n elif isinstance(v, (dict, list)):\n stack.append(v)", "config_hash": "08b02cf1d51b4a70", "take_control_of_blueprint": false, "category": null, "wait": true, "enabled": null, "run_actions": false, "MandatoryBPS": false, "BestPracticeKey": null}, "execution_time_ms": 1540.0571823120117, "success": true, "error_message": null, "response_size_bytes": 9229, "user_context": null}
{"timestamp": "2026-10-15T13:23:54.831977+00:00", "tool_name": "ha_config_set_script", "parameters": {"script_id": "spoolman_set_spool_remaining", "config": null, "python_transform": "_repl = [(\"CFS slot number 1-4 - resolves the spool by the slot color hex\", \"CFS slot number 1-4 - resolves the spool by the slot's CFS Lite location\"), (\"register a spool with that color hex and location in Spoolman, then try again.\", \"register a spool with that CFS Lite location in Spoolman, then try again.\"), (\"Pass slot (1-4) to resolve the spool by the CFS slot color hex in the CFS Lite location\", \"Pass slot (1-4) to resolve the spool by the CFS slot location in the CFS Lite\")]\nstack = [config]\nfor _ in range(20000):\n if not stack:\n break\n node = stack.pop()\n if isinstance(node, dict):\n for k in list(node.keys()):\n v = node[k]\n if isinstance(v, str):\n for a, b in _repl:\n if a in v:\n v = v.replace(a, b)\n node[k] = v\n elif isinstance(v, (dict, list)):\n stack.append(v)\n elif isinstance(node, list):\n for i in range(len(node)):\n v = node[i]\n if isinstance(v, str):\n for a, b in _repl:\n if a in v:\n v = v.replace(a, b)\n node[i] = v\n elif isinstance(v, (dict, list)):\n stack.append(v)", "config_hash": "47a9069453dcf38d", "take_control_of_blueprint": false, "category": null, "wait": true, "run": null, "variables": null, "MandatoryBPS": false, "BestPracticeKey": null}, "execution_time_ms": 1638.6640071868896, "success": true, "error_message": null, "response_size_bytes": 7396, "user_context": null}
{"timestamp": "2026-10-15T13:23:55.041771+00:00", "tool_name": "ha_config_set_automation", "parameters": {"config": null, "identifier": "1791477238799", "python_transform": "_repl = [(\"A single-colour job whose colour is in a loaded slot is checked exactly against that slot's spool; otherwise the\", \"A single-colour job is checked exactly against the spool in the print's active CFS slot; otherwise the\"), (\"No exact colour match for the print colour #{{ gcol | upper }} in a loaded CFS slot, so the exact spool cannot be identified.\", \"No active CFS slot reported for the print colour #{{ gcol | upper }}, so the exact spool cannot be identified.\")]\nstack = [config]\nfor _ in range(20000):\n if not stack:\n break\n node = stack.pop()\n if isinstance(node, dict):\n for k in list(node.keys()):\n v = node[k]\n if isinstance(v, str):\n for a, b in _repl:\n if a in v:\n v = v.replace(a, b)\n node[k] = v\n elif isinstance(v, (dict, list)):\n stack.append(v)\n elif isinstance(node, list):\n for i in range(len(node)):\n v = node[i]\n if isinstance(v, str):\n for a, b in _repl:\n if a in v:\n v = v.replace(a, b)\n node[i] = v\n elif isinstance(v, (dict, list)):\n stack.append(v)", "config_hash": "a2c48f9b809f1fb2", "take_control_of_blueprint": false, "category": null, "wait": true, "enabled": null, "run_actions": false, "MandatoryBPS": false, "BestPracticeKey": null}, "execution_time_ms": 1822.0086097717285, "success": true, "error_message": null, "response_size_bytes": 1582, "user_context": null}
+21 -22
View File
@@ -4554,9 +4554,9 @@
and per-slot gram counters and latches the active CFS slot. On every slot change
mid-print, deducts the exact extrusion of the finished segment (used_material_length
delta x g/cm) from the Spoolman spool in the CFS Lite location matching the previous
slot color hex (only if that spool has remaining weight), accumulates grams per
slot, notifies on no-match, then re-baselines the checkpoint and advances the
latch.'
slot''s CFS Lite location (only if that spool has remaining weight), accumulates
grams per slot, notifies on no-match, then re-baselines the checkpoint and advances
the latch.'
triggers:
- trigger: state
entity_id: sensor.sparkx_i7_print_status
@@ -4647,25 +4647,25 @@
default:
- action: notify.persistent_notification
data:
title: 'Spoolman: no spool for slot color'
title: 'Spoolman: no spool for the latched slot'
message: 'Segment of {{ grams }} g from {{ old_slot }} (color #{{ color
| upper }}) could not be deducted - no Spoolman spool in the CFS Lite
location with remaining weight matches that color. Register the new
roll in Spoolman with location CFS Lite, then adjust manually if needed.'
| upper }}) could not be deducted - no Spoolman spool with remaining
weight is in that slot''s CFS Lite location. Register the new roll
in Spoolman in that location, then adjust manually if needed.'
- action: notify.mobile_app_francos_ipad
data:
title: 'Spoolman: no spool for slot color'
title: 'Spoolman: no spool for the latched slot'
message: 'Segment of {{ grams }} g from {{ old_slot }} (color #{{ color
| upper }}) could not be deducted - no Spoolman spool in the CFS Lite
location with remaining weight matches that color. Register the new
roll in Spoolman with location CFS Lite, then adjust manually if needed.'
| upper }}) could not be deducted - no Spoolman spool with remaining
weight is in that slot''s CFS Lite location. Register the new roll
in Spoolman in that location, then adjust manually if needed.'
- action: notify.mobile_app_sm_f956w
data:
title: 'Spoolman: no spool for slot color'
title: 'Spoolman: no spool for the latched slot'
message: 'Segment of {{ grams }} g from {{ old_slot }} (color #{{ color
| upper }}) could not be deducted - no Spoolman spool in the CFS Lite
location with remaining weight matches that color. Register the new
roll in Spoolman with location CFS Lite, then adjust manually if needed.'
| upper }}) could not be deducted - no Spoolman spool with remaining
weight is in that slot''s CFS Lite location. Register the new roll
in Spoolman in that location, then adjust manually if needed.'
- action: input_number.set_value
target:
entity_id: input_number.sparkx_i7_spoolman_length_checkpoint
@@ -4776,10 +4776,10 @@
alias: SparkX i7 - Filament sufficiency check at print start
description: When a print starts and stays printing for 45 s, reports how much filament
the job needs, how much has already been used and how much is left, then compares
the loaded CFS Lite spools against that. A single-colour job whose colour is in
a loaded slot is checked exactly against that slot's spool; otherwise the slicer
gives no per-colour figure, so each loaded spool is compared against the whole
job total. Always sends a notification.
the loaded CFS Lite spools against that. A single-colour job is checked exactly
against the spool in the print's active CFS slot; otherwise the slicer gives no
per-colour figure, so each loaded spool is compared against the whole job total.
Always sends a notification.
triggers:
- trigger: state
entity_id: sensor.sparkx_i7_print_status
@@ -4948,9 +4948,8 @@
{% else %}Active slot {{ aslot }} 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
%}
{% elif single %}No active CFS slot reported for the print colour #{{ gcol
| upper }}, so the exact spool cannot be identified.{% if ns.cover %}
Would cover {{ job_g }} g:
+10 -9
View File
@@ -245,7 +245,8 @@ spoolman_set_spool_remaining:
fields:
slot:
name: CFS Slot
description: CFS slot number 1-4 - resolves the spool by the slot color hex
description: CFS slot number 1-4 - resolves the spool by the slot's CFS Lite
location
selector:
number:
min: 1
@@ -263,8 +264,8 @@ spoolman_set_spool_remaining:
- variables:
resolved_id: '{% set n = (slot | int(0)) if slot is defined else 0 %}{% if n
>= 1 %}{% set ns = namespace(id='''') %}{% for e in integration_entities(''spoolman'')
%}{% if e.endswith(''_color_hex'') and (state_attr(e[:-10], ''location'') |
default('''', true) | lower) == (''cfs lite '' ~ (n | int)) and ns.id ==
%}{% if e.endswith(''_color_hex'') and (state_attr(e[:-10], ''location'')
| default('''', true) | lower) == (''cfs lite '' ~ (n | int)) and ns.id ==
'''' %}{% set ns.id = states(e[:-10] ~ ''_id'') %}{% endif %}{% endfor %}{{
ns.id }}{% else %}{{ (spool_id | int(0)) if spool_id is defined else 0 }}{%
endif %}'
@@ -286,11 +287,11 @@ spoolman_set_spool_remaining:
message: '{% if slot_n | int >= 1 %}No Spoolman spool matched CFS slot {{
slot_n }} (color {{ states(''sensor.sparkx_i7_cfs_box_1_slot_'' ~ (slot_n
| int) ~ ''_color'') }}) in the CFS Lite location - register a spool with
that color hex and location in Spoolman, then try again.{% else %}No spool
resolved - pass spool_id or a CFS slot 1-4. Nothing was set.{% endif %}'
that CFS Lite location in Spoolman, then try again.{% else %}No spool resolved
- pass spool_id or a CFS slot 1-4. Nothing was set.{% endif %}'
mode: single
description: Sets a Spoolman spool remaining weight from the shared helper input_number.spoolman_set_remaining.
Pass slot (1-4) to resolve the spool by the CFS slot color hex in the CFS Lite
location (no remaining-weight guard, so an exhausted spool can be reset to full),
or pass spool_id directly. Notifies via persistent notification when nothing could
be resolved.
Pass slot (1-4) to resolve the spool by the CFS slot location in the CFS Lite
(no remaining-weight guard, so an exhausted spool can be reset to full), or pass
spool_id directly. Notifies via persistent notification when nothing could be
resolved.