From 3355f0dda871ae4d987d697f880366fc24950c7b Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Sun, 21 Jun 2026 21:04:41 +0300 Subject: [PATCH] fix: harden Washing Machine remaining-time parsing for unavailable states Treat 'unavailable'/'none'/'-'/'' remaining-time values as not-running and parse with int(0) defaults so a partially invalid sensor value degrades to 0 instead of raising. Bump manifest to 2.14.1. --- Common/Washing Machine/blueprint.yaml | 27 +++++++++++++++------------ manifest.json | 2 +- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Common/Washing Machine/blueprint.yaml b/Common/Washing Machine/blueprint.yaml index b771dea..86bd3f3 100644 --- a/Common/Washing Machine/blueprint.yaml +++ b/Common/Washing Machine/blueprint.yaml @@ -553,15 +553,17 @@ variables: and run_state not in non_running_state_ids and run_state != preparation_state_id and run_state != run_state_completion_id - and remaining not in ['unknown', 'unavailable'] }} + and (remaining | string | trim) not in ['unknown', 'unavailable', 'none', '-', ''] }} - # Parse remaining time string (hh:mm:ss) to total minutes + # Parse remaining time string (hh:mm:ss) to total minutes. + # Use int(0) defaults so a partially invalid sensor value (e.g. + # 'unavailable:00:00') degrades to 0 instead of raising. remaining_time_in_minutes: > - {% if remaining not in ['unknown', 'unavailable', '-'] %} - {% set parts = remaining.split(':') %} + {% set r = remaining | string | trim %} + {% if r not in ['unknown', 'unavailable', 'none', '-', ''] %} + {% set parts = r.split(':') %} {% if parts | length >= 2 %} - {% set total = parts[0]|int * 60 + parts[1]|int %} - {{ total }} + {{ parts[0] | int(0) * 60 + parts[1] | int(0) }} {% else %} {{ 0 }} {% endif %} @@ -571,11 +573,12 @@ variables: # Calculate estimated end time from remaining time estimated_end_time: > - {% if remaining not in ['unknown', 'unavailable', '-'] %} - {% set parts = remaining.split(':') %} + {% set r = remaining | string | trim %} + {% if r not in ['unknown', 'unavailable', 'none', '-', ''] %} + {% set parts = r.split(':') %} {% if parts | length >= 2 %} - {% set hours = parts[0] | int %} - {% set minutes = parts[1] | int %} + {% set hours = parts[0] | int(0) %} + {% set minutes = parts[1] | int(0) %} {% set end_time = now() + timedelta(hours=hours, minutes=minutes) %} {{ end_time.strftime('%H:%M') }} {% else %} @@ -739,7 +742,7 @@ action: value_template: > {{ not is_running and automation_state.get(state_notification_about_start_sent, false) - and (states(run_state_sensor) in [run_state_completion_id, 'unknown', '-'] or states(remaining_time_sensor) in ['unknown', '-']) }} + and (states(run_state_sensor) in [run_state_completion_id, 'unknown', 'unavailable', '-'] or states(remaining_time_sensor) in ['unknown', 'unavailable', '-']) }} sequence: - variables: # Calculate energy consumption @@ -891,7 +894,7 @@ action: - variables: # Calculate minutes for the template - minutes: "{{ remaining.split(':')[1] | int }}" + minutes: "{{ remaining.split(':')[1] | int(0) if ':' in (remaining | string) else 0 }}" # Render the message template with available variables message: > {% set tpl = message_almost_done_template %} diff --git a/manifest.json b/manifest.json index 4af42bf..7468b8e 100644 --- a/manifest.json +++ b/manifest.json @@ -1,3 +1,3 @@ { - "version": "2.14.0" + "version": "2.14.1" }