From adbee2d8647fec5510c94000439b589ec03b6dfd Mon Sep 17 00:00:00 2001 From: Home Assistant Version Control Date: Mon, 12 Oct 2026 16:33:17 +0000 Subject: [PATCH] 3 files --- ...omation.1791477238729.20261012_163311.yaml | 171 ++++++++++++++++++ .ha_mcp/logs/mcp_usage.jsonl | 1 + automations.yaml | 6 +- 3 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 .ha_mcp/backups/automation.1791477238729.20261012_163311.yaml diff --git a/.ha_mcp/backups/automation.1791477238729.20261012_163311.yaml b/.ha_mcp/backups/automation.1791477238729.20261012_163311.yaml new file mode 100644 index 00000000..6398f09e --- /dev/null +++ b/.ha_mcp/backups/automation.1791477238729.20261012_163311.yaml @@ -0,0 +1,171 @@ +# ha_mcp_backup +schema_version: 1 +domain: automation +entity_id: '1791477238729' +captured: '2026-10-12T16:33:11.682946+00:00' +tool: ha_config_set_automation +config: + id: '1791477238729' + alias: SparkX i7 - Deduct filament in Spoolman on print complete + description: On print completion, deducts the final segment (used_material_length + delta since last checkpoint x g/cm) from the Spoolman spool in the CFS Lite location + matching the latched slot color (remaining weight > 0 guard), accumulates it per + slot, then sends a summary notification with total and per-slot breakdown whenever + anything was deducted. Silent when total is 0. Clears the latch and re-baselines + the checkpoint. + triggers: + - trigger: state + entity_id: sensor.sparkx_i7_print_status + from: printing + to: completed + id: complete + - trigger: state + entity_id: sensor.sparkx_i7_print_status + to: stopped + id: stopped + - trigger: state + entity_id: sensor.sparkx_i7_print_status + to: error + id: error + conditions: + - condition: template + value_template: '{{ trigger.id == ''complete'' or states(''input_text.sparkx_i7_print_spool_latch'') + not in ['''', ''unknown'', ''unavailable''] }}' + actions: + - variables: + old_slot: '{{ states(''input_text.sparkx_i7_print_spool_latch'') }}' + cur: '{{ states(''sensor.sparkx_i7_used_material_length'') | float(0) }}' + checkpoint: '{{ states(''input_number.sparkx_i7_spoolman_length_checkpoint'') + | float(0) }}' + outcome: '{% set tid = trigger.id | default(''complete'') %}{{ ''cancelled'' + if tid == ''stopped'' else (''error'' if tid == ''error'' else ''complete'') + }}' + - variables: + final_grams: '{{ (([cur | float - (checkpoint | float), 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 (states(e) | replace(''#'', '''') | + lower) == color and (state_attr(e[:-10], ''location'') | default('''', true) + | lower) == ''cfs lite'' %}{% set b = e[:-10] %}{% if (states(b) | float(0)) + > 0 and ns.id == '''' %}{% set ns.id = states(b ~ ''_id'') %}{% endif %}{% + endif %}{% endfor %}{{ ns.id }}' + - variables: + helper_idx: '{{ old_slot.split('' '')[-1] if old_slot.split('' '')[-1] in [''1'', + ''2'', ''3'', ''4''] else '''' }}' + - variables: + nonhelper_g: '{{ final_grams if (final_grams | float > 0) and (spool_id not + in ['''', ''unknown'', ''unavailable'']) and (helper_idx == '''') else 0 }}' + - if: + condition: template + value_template: '{{ final_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: '{{ final_grams | float(0) }}' + - if: + condition: template + value_template: '{{ helper_idx != '''' }}' + then: + - action: input_number.set_value + target: + entity_id: input_number.sparkx_i7_slot_{{ helper_idx }}_grams + data: + value: '{{ (states(''input_number.sparkx_i7_slot_'' ~ helper_idx ~ ''_grams'') + | float(0)) + (final_grams | float) }}' + default: + - action: notify.persistent_notification + data: + title: 'Spoolman: no spool for slot color' + message: 'Print {{ outcome }}: final segment of {{ final_grams }} g from + {{ old_slot if old_slot else ''the active 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: 'Print {{ outcome }}: final segment of {{ final_grams }} g from + {{ old_slot if old_slot else ''the active 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: 'Print {{ outcome }}: final segment of {{ final_grams }} g from + {{ old_slot if old_slot else ''the active 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.' + - variables: + summary_total: '{% set ns = namespace(t = 0) %}{% for n in [''1'', ''2'', ''3'', + ''4''] %}{% set g = states(''input_number.sparkx_i7_slot_'' ~ n ~ ''_grams'') + | float(0) %}{% if g > 0 %}{% set ns.t = ns.t + g %}{% endif %}{% endfor %}{{ + (ns.t + (nonhelper_g | float)) | round(1) }}' + - variables: + summary_lines: '{% set ns = namespace(l = []) %}{% for n in [''1'', ''2'', ''3'', + ''4''] %}{% set g = states(''input_number.sparkx_i7_slot_'' ~ n ~ ''_grams'') + | float(0) %}{% if g > 0 %}{% set ns.l = ns.l + [''Slot '' ~ n ~ '' ('' ~ + states(''sensor.sparkx_i7_slot_'' ~ n ~ ''_color_name'') ~ ''): '' ~ (g | + round(1)) ~ '' g''] %}{% endif %}{% endfor %}{% if nonhelper_g | float > 0 + %}{% set ns.l = ns.l + [(old_slot if old_slot else ''Unlatched'') ~ '': '' + ~ (nonhelper_g | float | round(1)) ~ '' g''] %}{% endif %}{{ ns.l | join(''\n'') + }}' + - if: + condition: template + value_template: '{{ summary_total | float > 0 }}' + then: + - action: notify.persistent_notification + data: + title: Print {{ outcome }} - Spoolman updated + message: 'Print {{ outcome }} - Spoolman deducted {{ summary_total }} g + + {{ summary_lines }}' + - action: notify.mobile_app_francos_ipad + data: + title: Print {{ outcome }} - Spoolman updated + message: 'Print {{ outcome }} - Spoolman deducted {{ summary_total }} g + + {{ summary_lines }}' + - action: notify.mobile_app_sm_f956w + data: + title: Print {{ outcome }} - Spoolman updated + message: 'Print {{ outcome }} - Spoolman deducted {{ summary_total }} g + + {{ summary_lines }}' + - if: + condition: template + value_template: '{{ trigger.id == ''complete'' }}' + then: + - action: input_number.set_value + target: + entity_id: input_number.sparkx_i7_last_job_filament_weight + data: + value: '{{ final_grams }}' + - action: input_number.set_value + target: + entity_id: input_number.sparkx_i7_last_job_cost + data: + value: '{{ ((final_grams | float) * (states(''input_number.filament_price_per_kg'') + | float(25)) / 1000) | round(2) }}' + - 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: '' + mode: single diff --git a/.ha_mcp/logs/mcp_usage.jsonl b/.ha_mcp/logs/mcp_usage.jsonl index 7ed9f4a5..b6c160fa 100644 --- a/.ha_mcp/logs/mcp_usage.jsonl +++ b/.ha_mcp/logs/mcp_usage.jsonl @@ -4463,3 +4463,4 @@ {"timestamp": "2026-10-12T16:31:21.696328+00:00", "tool_name": "ha_config_set_automation", "parameters": {"config": null, "identifier": "1791477238762", "python_transform": "stack = [config]\nfor _ in range(500):\n if not stack:\n break\n node = stack.pop()\n if isinstance(node, dict):\n for k in list(node.keys()):\n if isinstance(node[k], str) and \"split(' ')\" in node[k]:\n node[k] = node[k].replace(\"split(' ')\", \"split('_')\")\n elif isinstance(node[k], (dict, list)):\n stack.append(node[k])\n elif isinstance(node, list):\n for i in range(len(node)):\n if isinstance(node[i], str) and \"split(' ')\" in node[i]:\n node[i] = node[i].replace(\"split(' ')\", \"split('_')\")\n elif isinstance(node[i], (dict, list)):\n stack.append(node[i])", "config_hash": "67883587a6616a08", "take_control_of_blueprint": false, "category": null, "wait": true, "enabled": null, "run_actions": false, "MandatoryBPS": false, "BestPracticeKey": null}, "execution_time_ms": 1297.755241394043, "success": true, "error_message": null, "response_size_bytes": 7691, "user_context": null} {"timestamp": "2026-10-12T16:31:26.410364+00:00", "tool_name": "ha_reload_core", "parameters": {"target": "automations", "entry_id": null}, "execution_time_ms": 198.5642910003662, "success": true, "error_message": null, "response_size_bytes": 122, "user_context": null} {"timestamp": "2026-10-12T16:32:55.190572+00:00", "tool_name": "ha_config_get_automation", "parameters": {"identifier": "1791477238729"}, "execution_time_ms": 262.2084617614746, "success": true, "error_message": null, "response_size_bytes": 7041, "user_context": null} +{"timestamp": "2026-10-12T16:33:12.207589+00:00", "tool_name": "ha_config_set_automation", "parameters": {"config": null, "identifier": "1791477238729", "python_transform": "config['actions'][3]['variables']['helper_idx'] = \"{{ old_slot.split('_')[-1] if old_slot.split('_')[-1] in ['1', '2', '3', '4'] else '' }}\"\nconfig['actions'][9]['then'][0]['data']['value'] = \"{{ summary_total }}\"\nconfig['actions'][9]['then'][1]['data']['value'] = \"{{ ((summary_total | float) * (states('input_number.filament_price_per_kg') | float(25)) / 1000) | round(2) }}\"", "config_hash": "5cb56a9f45956b0d", "take_control_of_blueprint": false, "category": null, "wait": true, "enabled": null, "run_actions": false, "MandatoryBPS": false, "BestPracticeKey": null}, "execution_time_ms": 476.5012264251709, "success": true, "error_message": null, "response_size_bytes": 7395, "user_context": null} diff --git a/automations.yaml b/automations.yaml index 610807f2..20e78840 100644 --- a/automations.yaml +++ b/automations.yaml @@ -4432,7 +4432,7 @@ > 0 and ns.id == '''' %}{% set ns.id = states(b ~ ''_id'') %}{% endif %}{% endif %}{% endfor %}{{ ns.id }}' - variables: - helper_idx: '{{ old_slot.split('' '')[-1] if old_slot.split('' '')[-1] in [''1'', + helper_idx: '{{ old_slot.split(''_'')[-1] if old_slot.split(''_'')[-1] in [''1'', ''2'', ''3'', ''4''] else '''' }}' - variables: nonhelper_g: '{{ final_grams if (final_grams | float > 0) and (spool_id not @@ -4530,12 +4530,12 @@ target: entity_id: input_number.sparkx_i7_last_job_filament_weight data: - value: '{{ final_grams }}' + value: '{{ summary_total }}' - action: input_number.set_value target: entity_id: input_number.sparkx_i7_last_job_cost data: - value: '{{ ((final_grams | float) * (states(''input_number.filament_price_per_kg'') + value: '{{ ((summary_total | float) * (states(''input_number.filament_price_per_kg'') | float(25)) / 1000) | round(2) }}' - action: input_number.set_value target: