6 files
This commit is contained in:
@@ -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.
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user