Files
Home-Assistant/blueprints/automation/nberktumer/spaghetti_detection.yaml
2025-06-24 12:12:01 -04:00

515 lines
18 KiB
YAML

blueprint:
name: Bambu Lab - Spaghetti Detection
description: Bambu Lab - Spaghetti Detection
domain: automation
input:
home_assistant_host:
name: Home Assistant Host
description: Home Assistant host
default: http://192.168.1.123:8123
obico_host:
name: Obico ML API Host
description: Obico ML API host
default: http://192.168.1.123:3333
obico_auth_token:
name: Obico ML API Auth Token
description: Obico ML API authentication token
default: obico_api_secret
detection_frequency:
name: Detection Frequency
description: The detection algorithm will run in every defined seconds
default: /5
selector:
select:
options:
- label: Every second
value: /1
- label: Every 5 seconds
value: /5
- label: Every 10 seconds
value: /10
- label: Every 30 seconds
value: /30
- label: Every 60 seconds
value: /59
multiple: false
mode: dropdown
sort: false
custom_value: false
auto_turn_on_light:
name: Automatically Turn On Printer Lights
description: Turns on printer lights before spaghetti detection operation
default: true
selector:
boolean: {}
notification_settings:
name: Notification Settings
description: Type of notification to send after detecting a failure
default: standard
selector:
select:
mode: dropdown
options:
- label: Critical Notification
value: critical
- label: Standard Notification
value: standard
- label: None
value: none
sort: false
multiple: false
custom_value: false
failure_action:
name: On Failure Action
description: What to do after detecting a failure
default: pause
selector:
select:
mode: dropdown
options:
- label: Pause
value: pause
- label: Stop
value: stop
- label: Warn
value: warn
sort: false
multiple: false
custom_value: false
notification_service:
name: Mobile devices notification service
description: The notification service for mobile devices (eg. notify.mobile_app_<your_device_id_here>).
You can provide both a notify group or a single notify device here.
default: notify.notify
selector:
text: {}
printer_print_status_sensor:
name: Printer Print Status Sensor
description: Bambu Lab printer print status sensor
selector:
entity:
filter:
- integration: bambu_lab
domain:
- sensor
device_class:
- enum
multiple: false
printer_current_stage_sensor:
name: Printer Current Stage Sensor
description: Bambu Lab printer current stage sensor
selector:
entity:
filter:
- integration: bambu_lab
domain:
- sensor
device_class:
- enum
multiple: false
printer_camera:
name: Printer Camera Entity
description: Bambu Lab printer camera entity
selector:
entity:
filter:
- domain:
- camera
multiple: false
printer_pause_button:
name: Printer Pause Button Entity
description: Bambu Lab printer pause button entity
selector:
entity:
filter:
- integration: bambu_lab
domain:
- button
multiple: false
printer_resume_button:
name: Printer Resume Button Entity
description: Bambu Lab printer resume button entity
selector:
entity:
filter:
- integration: bambu_lab
domain:
- button
multiple: false
printer_stop_button:
name: Printer Stop Button Entity
description: Bambu Lab printer stop button entity
selector:
entity:
filter:
- integration: bambu_lab
domain:
- button
multiple: false
printer_chamber_light:
name: Printer Chamber Light
description: Bambu Lab printer chamber light
selector:
entity:
filter:
- integration: bambu_lab
domain:
- light
multiple: false
source_url: https://github.com/nberktumer/ha-bambu-lab-p1-spaghetti-detection/blob/main/blueprints/spaghetti_detection.yaml
variables:
HOME_ASSISTANT_HOST_VAR: !input home_assistant_host
PRINTER_CAMERA_VAR: !input printer_camera
FAILURE_ACTION_VAR: !input failure_action
NOTIFICATION_SETTINGS_VAR: !input notification_settings
DETECTION_FREQUENCY_VAR: !input detection_frequency
mode: single
max_exceeded: silent
trigger:
- platform: state
entity_id:
- !input printer_current_stage_sensor
to: printing
id: BAMBU_LAB_PRINTER_STAGE_CHANGE
- platform: event
event_type: mobile_app_notification_action
id: BAMBU_LAB_PAUSE_PRINTING
event_data:
action: BAMBU_LAB_PAUSE_PRINTING
- platform: event
event_type: mobile_app_notification_action
id: BAMBU_LAB_RESUME_PRINTING
event_data:
action: BAMBU_LAB_RESUME_PRINTING
- platform: event
event_type: mobile_app_notification_action
id: BAMBU_LAB_STOP_PRINTING
event_data:
action: BAMBU_LAB_STOP_PRINTING
- trigger: time_pattern
id: BAMBU_LAB_DETECTION_TRIGGER
seconds: !input detection_frequency
condition: []
action:
- choose:
- conditions:
- condition: trigger
id: BAMBU_LAB_PRINTER_STAGE_CHANGE
sequence:
- service: number.set_value
data:
value: 0
target:
entity_id:
- number.bambu_lab_p1_spaghetti_detection_current_frame_number
- number.bambu_lab_p1_spaghetti_detection_ewm_mean
- number.bambu_lab_p1_spaghetti_detection_rolling_mean_short
- number.bambu_lab_p1_spaghetti_detection_rolling_mean_long
- number.bambu_lab_p1_spaghetti_detection_normalized_p
- number.bambu_lab_p1_spaghetti_detection_adjusted_ewm_mean
- number.bambu_lab_p1_spaghetti_detection_p_sum
- if:
- condition: and
conditions:
- condition: state
entity_id: !input printer_chamber_light
state: 'off'
- condition: template
value_template: !input auto_turn_on_light
then:
- service: light.turn_on
target:
entity_id:
- !input printer_chamber_light
- conditions:
- condition: trigger
id:
- BAMBU_LAB_PAUSE_PRINTING
- BAMBU_LAB_RESUME_PRINTING
- BAMBU_LAB_STOP_PRINTING
sequence:
- choose:
- conditions:
- condition: trigger
id:
- BAMBU_LAB_PAUSE_PRINTING
sequence:
- service: button.press
data: {}
target:
entity_id: !input printer_pause_button
- conditions:
- condition: trigger
id: BAMBU_LAB_RESUME_PRINTING
sequence:
- service: button.press
data: {}
target:
entity_id: !input printer_resume_button
- conditions:
- condition: trigger
id: BAMBU_LAB_STOP_PRINTING
sequence:
- service: button.press
data: {}
target:
entity_id: !input printer_stop_button
- conditions:
- condition: trigger
id: BAMBU_LAB_DETECTION_TRIGGER
sequence:
- if:
- condition: not
conditions:
- condition: state
entity_id: !input printer_print_status_sensor
state: running
then:
- stop: ''
- if:
- condition: template
value_template: '{{ now().second % DETECTION_FREQUENCY_VAR > 0 }}'
then:
- stop: ''
- if:
- condition: and
conditions:
- condition: state
entity_id: !input printer_chamber_light
state: 'off'
- condition: template
value_template: !input auto_turn_on_light
then:
- service: light.turn_on
target:
entity_id:
- !input printer_chamber_light
- service: bambu_lab_p1_spaghetti_detection.predict
data:
obico_host: !input obico_host
obico_auth_token: !input obico_auth_token
image_url: '{{ HOME_ASSISTANT_HOST_VAR }}{{ state_attr(PRINTER_CAMERA_VAR,
''entity_picture'') }}'
response_variable: result
- service: number.set_value
data:
value: '{{ result.result.detections | map(attribute=1) | sum | float }}'
target:
entity_id: number.bambu_lab_p1_spaghetti_detection_p_sum
- service: number.set_value
data:
value: '{{ states(''number.bambu_lab_p1_spaghetti_detection_current_frame_number'')
| float + 1 }}'
target:
entity_id: number.bambu_lab_p1_spaghetti_detection_current_frame_number
- service: number.set_value
data:
value: '{{ states(''number.bambu_lab_p1_spaghetti_detection_lifetime_frame_number'')
| float + 1 }}'
target:
entity_id: number.bambu_lab_p1_spaghetti_detection_lifetime_frame_number
- service: number.set_value
data:
value: '{{ (states(''number.bambu_lab_p1_spaghetti_detection_p_sum'') | float)
* (2 / (12 + 1)) + (states(''number.bambu_lab_p1_spaghetti_detection_ewm_mean'')
| float) * (1 - (2 / (12 + 1))) }}'
target:
entity_id: number.bambu_lab_p1_spaghetti_detection_ewm_mean
- service: number.set_value
data:
value: '{{ (states(''number.bambu_lab_p1_spaghetti_detection_rolling_mean_short'')
| float) + ((states(''number.bambu_lab_p1_spaghetti_detection_p_sum'') |
float) - (states(''number.bambu_lab_p1_spaghetti_detection_rolling_mean_short'')
| float)) / (310 if 310 <= (states(''number.bambu_lab_p1_spaghetti_detection_current_frame_number'')
| float) else (states(''number.bambu_lab_p1_spaghetti_detection_current_frame_number'')
| float) + 1) }}'
target:
entity_id: number.bambu_lab_p1_spaghetti_detection_rolling_mean_short
- service: number.set_value
data:
value: '{{ (states(''number.bambu_lab_p1_spaghetti_detection_rolling_mean_long'')
| float) + ((states(''number.bambu_lab_p1_spaghetti_detection_p_sum'') |
float) - (states(''number.bambu_lab_p1_spaghetti_detection_rolling_mean_long'')
| float)) / (7200 if 7200 <= (states(''number.bambu_lab_p1_spaghetti_detection_lifetime_frame_number'')
| float) else (states(''number.bambu_lab_p1_spaghetti_detection_lifetime_frame_number'')
| float) + 1) }}'
entity_id: number.bambu_lab_p1_spaghetti_detection_rolling_mean_long
- if:
- condition: numeric_state
entity_id: number.bambu_lab_p1_spaghetti_detection_current_frame_number
below: 30
then:
- stop: ''
alias: if current_frame_num < 30
- service: number.set_value
data:
value: '{{ (states(''number.bambu_lab_p1_spaghetti_detection_ewm_mean'') |
float) - (states(''number.bambu_lab_p1_spaghetti_detection_rolling_mean_long'')
| float) }}'
target:
entity_id: number.bambu_lab_p1_spaghetti_detection_adjusted_ewm_mean
- service: number.set_value
data:
value: '{{ ((states(''number.bambu_lab_p1_spaghetti_detection_rolling_mean_short'')
| float) - (states(''number.bambu_lab_p1_spaghetti_detection_rolling_mean_long'')
| float)) * 3.8 }}'
target:
entity_id: number.bambu_lab_p1_spaghetti_detection_rolling_mean_diff
- service: number.set_value
data:
value: '{{ min(0.78, max(0.33, (states(''number.bambu_lab_p1_spaghetti_detection_rolling_mean_diff'')
| float))) }}'
target:
entity_id: number.bambu_lab_p1_spaghetti_detection_thresh_warning
- service: number.set_value
data:
value: '{{ (states(''number.bambu_lab_p1_spaghetti_detection_thresh_warning'')
| float) * 1.75 }}'
target:
entity_id: number.bambu_lab_p1_spaghetti_detection_thresh_failure
- service: number.set_value
data:
value: '{{ (states(''number.bambu_lab_p1_spaghetti_detection_ewm_mean'') |
float) - (states(''number.bambu_lab_p1_spaghetti_detection_rolling_mean_long'')
| float) }}'
target:
entity_id: number.bambu_lab_p1_spaghetti_detection_p
- choose:
- conditions:
- condition: numeric_state
entity_id: number.bambu_lab_p1_spaghetti_detection_p
above: number.bambu_lab_p1_spaghetti_detection_thresh_failure
sequence:
- service: number.set_value
data:
value: '{{ min(1.0, max(2.0 / 3.0, ((((states(''number.bambu_lab_p1_spaghetti_detection_p'')
| float) - (states(''number.bambu_lab_p1_spaghetti_detection_thresh_failure'')
| float)) * (1.0 - 2.0 / 3.0)) / ((states(''number.bambu_lab_p1_spaghetti_detection_thresh_failure'')
| float) * 1.5 - (states(''number.bambu_lab_p1_spaghetti_detection_thresh_failure'')
| float))) + 2.0 / 3.0)) }}'
target:
entity_id: number.bambu_lab_p1_spaghetti_detection_normalized_p
- conditions:
- condition: numeric_state
entity_id: number.bambu_lab_p1_spaghetti_detection_p
above: number.bambu_lab_p1_spaghetti_detection_thresh_warning
sequence:
- service: number.set_value
data:
value: '{{ min(2.0 / 3.0, max(1.0 / 3.0, ((((states(''number.bambu_lab_p1_spaghetti_detection_p'')
| float) - (states(''number.bambu_lab_p1_spaghetti_detection_thresh_warning'')
| float)) * (2.0 / 3.0 - 1.0 / 3.0)) / ((states(''number.bambu_lab_p1_spaghetti_detection_thresh_failure'')
| float) - (states(''number.bambu_lab_p1_spaghetti_detection_thresh_warning'')
| float))) + 1.0 / 3.0)) }}'
target:
entity_id: number.bambu_lab_p1_spaghetti_detection_normalized_p
default:
- service: number.set_value
data:
value: '{{ min(1.0 / 3.0, max(0, ((states(''number.bambu_lab_p1_spaghetti_detection_p'')
| float) * 1.0 / 3.0) / (states(''number.bambu_lab_p1_spaghetti_detection_thresh_warning'')
| float))) }}'
target:
entity_id: number.bambu_lab_p1_spaghetti_detection_normalized_p
- if:
- condition: numeric_state
entity_id: number.bambu_lab_p1_spaghetti_detection_adjusted_ewm_mean
below: 0.38
then:
- stop: ''
- if:
- condition: and
conditions:
- condition: numeric_state
entity_id: number.bambu_lab_p1_spaghetti_detection_adjusted_ewm_mean
below: 0.78
- condition: numeric_state
entity_id: number.bambu_lab_p1_spaghetti_detection_adjusted_ewm_mean
below: number.bambu_lab_p1_spaghetti_detection_rolling_mean_diff
then:
- stop: ''
- if:
- condition: template
value_template: '{{ now() - states(''datetime.bambu_lab_p1_spaghetti_detection_last_notify_time'')
| as_datetime | as_local < timedelta(minutes=1) }}'
then:
- stop: ''
alias: if now() - last_notify_time < 1min
- choose:
- conditions:
- condition: template
value_template: '{{ FAILURE_ACTION_VAR == ''pause'' }}'
sequence:
- service: button.press
data: {}
target:
entity_id: !input printer_pause_button
- conditions:
- condition: template
value_template: '{{ FAILURE_ACTION_VAR == ''stop'' }}'
sequence:
- service: button.press
data: {}
target:
entity_id: !input printer_stop_button
- choose:
- conditions:
- condition: template
value_template: '{{ NOTIFICATION_SETTINGS_VAR == ''critical'' }}'
sequence:
- service: !input notification_service
data:
title: Bambu Lab - Spaghetti Detected
message: 'Confidence: {{ (states(''number.bambu_lab_p1_spaghetti_detection_normalized_p'')
| float * 100) | int }}%'
data:
image: '{{ HOME_ASSISTANT_HOST_VAR }}{{ state_attr(PRINTER_CAMERA_VAR,
''entity_picture'') }}'
ttl: 0
priority: high
channel: alarm_stream
push:
sound:
name: default
critical: 1
volume: 0.75
actions:
- action: BAMBU_LAB_RESUME_PRINTING
title: Resume Printing
- action: BAMBU_LAB_STOP_PRINTING
title: Stop Printing
- conditions:
- condition: template
value_template: '{{ NOTIFICATION_SETTINGS_VAR == ''standard'' }}'
sequence:
- service: !input notification_service
data:
title: Bambu Lab - Spaghetti Detected
message: 'Confidence: {{ (states(''number.bambu_lab_p1_spaghetti_detection_normalized_p'')
| float * 100) | int }}%'
data:
image: '{{ HOME_ASSISTANT_HOST_VAR }}{{ state_attr(PRINTER_CAMERA_VAR,
''entity_picture'') }}'
actions:
- action: BAMBU_LAB_RESUME_PRINTING
title: Resume Printing
- action: BAMBU_LAB_STOP_PRINTING
title: Stop Printing
- service: number.set_value
data:
value: 0
target:
entity_id:
- number.bambu_lab_p1_spaghetti_detection_current_frame_number
- number.bambu_lab_p1_spaghetti_detection_ewm_mean
- number.bambu_lab_p1_spaghetti_detection_rolling_mean_short
- number.bambu_lab_p1_spaghetti_detection_rolling_mean_long
- number.bambu_lab_p1_spaghetti_detection_normalized_p
- number.bambu_lab_p1_spaghetti_detection_adjusted_ewm_mean
- number.bambu_lab_p1_spaghetti_detection_p_sum
- service: datetime.set_value
data:
datetime: '{{ now() }}'
target:
entity_id: datetime.bambu_lab_p1_spaghetti_detection_last_notify_time