Console settings: add post-update verification in with_retry flows; introduce _verify_console_param_value and use it to verify retain final state, general params, and RuleN enable; keep non-retry path behavior. Improves reliability and ensures updates actually took.

This commit is contained in:
Mike Geppert 2025-08-09 11:01:58 -05:00
parent 9646099a4f
commit d4b29c2359

View File

@ -1458,8 +1458,15 @@ class TasmotaDiscovery:
response = requests.get(url, timeout=5)
if response.status_code == 200:
self.logger.debug(f"{name}: Set {param} to {final_value} (step 2 of 2 to update MQTT broker retain settings)")
console_updated = True
success = True
# Verify the change took effect
verified = self._verify_console_param_value(ip, name, param, final_value)
if verified:
console_updated = True
success = True
else:
self.logger.warning(f"{name}: Verification failed for {param} after update; retrying (attempt {attempts}/{max_attempts})")
if attempts < max_attempts:
time.sleep(1)
else:
self.logger.warning(f"{name}: Failed to set {param} to {final_value} (attempt {attempts}/{max_attempts})")
last_error = f"HTTP {response.status_code}"
@ -1596,8 +1603,14 @@ class TasmotaDiscovery:
self.logger.info(f"{name}: Set rule {param} to '{value}'")
else:
self.logger.debug(f"{name}: Set console parameter {param} to {value}")
console_updated = True
success = True
# Verify the change took effect before marking success
if self._verify_console_param_value(ip, name, param, value):
console_updated = True
success = True
else:
self.logger.warning(f"{name}: Verification failed for {param} after update; retrying (attempt {attempts}/{max_attempts})")
if attempts < max_attempts:
time.sleep(1)
else:
self.logger.warning(f"{name}: Failed to set console parameter {param} (attempt {attempts}/{max_attempts})")
last_error = f"HTTP {response.status_code}"
@ -1685,8 +1698,13 @@ class TasmotaDiscovery:
response = requests.get(url, timeout=5)
if response.status_code == 200:
self.logger.info(f"{name}: Auto-enabled {rule_enable_param}")
console_updated = True
success = True
if self._verify_console_param_value(ip, name, rule_enable_param, "1"):
console_updated = True
success = True
else:
self.logger.warning(f"{name}: Verification failed for {rule_enable_param} after update; retrying (attempt {attempts}/{max_attempts})")
if attempts < max_attempts:
time.sleep(1)
else:
self.logger.warning(f"{name}: Failed to auto-enable {rule_enable_param} (attempt {attempts}/{max_attempts})")
last_error = f"HTTP {response.status_code}"
@ -1724,6 +1742,50 @@ class TasmotaDiscovery:
return console_updated
def _verify_console_param_value(self, ip, name, param, expected):
"""Post-update verification; returns True if device value equals expected.
Normalizes values:
- ruleN (lowercase) compare rules text (case/whitespace-insensitive)
- RuleN (uppercase) consider ON/1/enabled as True when expected is truthy ('1','on')
- Generic: normalize 'on'/'off' vs '1'/'0'
"""
try:
cur, ok = self._get_console_param_value(ip, name, param)
if not ok:
return False
# Rule definition verify
if param.lower().startswith('rule') and param.islower() and param[-1].isdigit():
import re as _re
def _norm(s):
s = str(s or '')
s = s.strip().lower()
s = _re.sub(r"\s+", " ", s)
return s
return _norm(cur) == _norm(expected)
# Rule enable verify (RuleN)
if param.lower().startswith('rule') and not param.islower() and param[-1].isdigit():
val = str(cur or '').strip().lower()
if val in ('on','enabled','active'):
val = '1'
if val in ('off','disabled','inactive'):
val = '0'
exp = str(expected or '').strip().lower()
if exp in ('on','enabled','active'):
exp = '1'
if exp in ('off','disabled','inactive'):
exp = '0'
return val == exp or val == '1'
# Generic verify
val = str(cur or '').strip().lower()
exp = str(expected or '').strip().lower()
if val in ('on','off') and exp in ('1','0'):
val = '1' if val=='on' else '0'
if val in ('1','0') and exp in ('on','off'):
val = 'on' if val=='1' else 'off'
return val == exp
except Exception:
return False
def _get_console_param_value(self, ip, name, param):
"""Query the device for the current value of a console parameter.
Returns (value, True) on success, (None, False) on failure.