TasmotaManager/git_diff.txt
Mike Geppert 126cd39555 Major code improvements and bug fixes:
1. Restructured configuration: Moved config_other and console to top level
2. Added common _match_pattern function for regex pattern matching
3. Implemented Unifi Hostname bug fix in is_hostname_unknown
4. Created common get_device_hostname function to eliminate code duplication
5. Added comprehensive test scripts for all new functionality
6. Added detailed documentation for all changes
2025-08-08 19:04:33 -05:00

258 lines
17 KiB
Plaintext

diff --git a/TasmotaManager.py b/TasmotaManager.py
index dab1ef3..0d5accf 100644
--- a/TasmotaManager.py
+++ b/TasmotaManager.py
@@ -547,10 +547,32 @@ class TasmotaDiscovery:
self.logger.debug(f"{name}: No mqtt.config_other settings found in configuration")
return False
- # Get Status 0 for device name from Configuration/Other page
+ # Get Status 0 for device name from Configuration/Other page with increased timeout
url_status0 = f"http://{ip}/cm?cmnd=Status%200"
- response = requests.get(url_status0, timeout=5)
- status0_data = response.json()
+ try:
+ self.logger.debug(f"{name}: Getting Status 0 with increased timeout (10 seconds)")
+ response = requests.get(url_status0, timeout=10)
+ status0_data = response.json()
+
+ # Log the actual response format for debugging
+ self.logger.debug(f"{name}: Status 0 response: {status0_data}")
+ except requests.exceptions.Timeout:
+ self.logger.error(f"{name}: Timeout getting Status 0 (10 seconds) - device may be busy")
+ # Try one more time with even longer timeout
+ try:
+ self.logger.debug(f"{name}: Retrying Status 0 with 20 second timeout")
+ response = requests.get(url_status0, timeout=20)
+ status0_data = response.json()
+ self.logger.debug(f"{name}: Status 0 response on retry: {status0_data}")
+ except requests.exceptions.Timeout:
+ self.logger.error(f"{name}: Timeout getting Status 0 even with 20 second timeout")
+ return False
+ except requests.exceptions.RequestException as e:
+ self.logger.error(f"{name}: Error getting Status 0 on retry: {str(e)}")
+ return False
+ except requests.exceptions.RequestException as e:
+ self.logger.error(f"{name}: Error getting Status 0: {str(e)}")
+ return False
# Extract device name from Status 0 response
device_name = status0_data.get("Status", {}).get("DeviceName", "")
@@ -560,13 +582,32 @@ class TasmotaDiscovery:
self.logger.debug(f"{name}: Device name from Configuration/Other page: {device_name}")
- # Get current template
+ # Get current template with increased timeout
url_template = f"http://{ip}/cm?cmnd=Template"
- response = requests.get(url_template, timeout=5)
- template_data = response.json()
-
- # Log the actual response format for debugging
- self.logger.debug(f"{name}: Template response: {template_data}")
+ try:
+ self.logger.debug(f"{name}: Getting template with increased timeout (10 seconds)")
+ response = requests.get(url_template, timeout=10)
+ template_data = response.json()
+
+ # Log the actual response format for debugging
+ self.logger.debug(f"{name}: Template response: {template_data}")
+ except requests.exceptions.Timeout:
+ self.logger.error(f"{name}: Timeout getting template (10 seconds) - device may be busy")
+ # Try one more time with even longer timeout
+ try:
+ self.logger.debug(f"{name}: Retrying with 20 second timeout")
+ response = requests.get(url_template, timeout=20)
+ template_data = response.json()
+ self.logger.debug(f"{name}: Template response on retry: {template_data}")
+ except requests.exceptions.Timeout:
+ self.logger.error(f"{name}: Timeout getting template even with 20 second timeout")
+ return False
+ except requests.exceptions.RequestException as e:
+ self.logger.error(f"{name}: Error getting template on retry: {str(e)}")
+ return False
+ except requests.exceptions.RequestException as e:
+ self.logger.error(f"{name}: Error getting template: {str(e)}")
+ return False
# Extract current template - handle different response formats
current_template = ""
@@ -609,32 +650,49 @@ class TasmotaDiscovery:
encoded_value = urllib.parse.quote(template_value)
url = f"http://{ip}/cm?cmnd=Template%20{encoded_value}"
- response = requests.get(url, timeout=5)
- if response.status_code == 200:
- self.logger.info(f"{name}: Template updated successfully")
-
- # Activate the template by setting module to 0 (Template module)
- self.logger.info(f"{name}: Activating template by setting module to 0")
- module_url = f"http://{ip}/cm?cmnd=Module%200"
- module_response = requests.get(module_url, timeout=5)
-
- if module_response.status_code == 200:
- self.logger.info(f"{name}: Module set to 0 successfully")
-
- # Restart the device to apply the template
- self.logger.info(f"{name}: Restarting device to apply template")
- restart_url = f"http://{ip}/cm?cmnd=Restart%201"
- restart_response = requests.get(restart_url, timeout=5)
+ try:
+ self.logger.debug(f"{name}: Setting template with 10 second timeout")
+ response = requests.get(url, timeout=10)
+ if response.status_code == 200:
+ self.logger.info(f"{name}: Template updated successfully")
- if restart_response.status_code == 200:
- self.logger.info(f"{name}: Device restart initiated successfully")
- template_updated = True
- else:
- self.logger.error(f"{name}: Failed to restart device")
+ # Activate the template by setting module to 0 (Template module)
+ self.logger.info(f"{name}: Activating template by setting module to 0")
+ module_url = f"http://{ip}/cm?cmnd=Module%200"
+ try:
+ module_response = requests.get(module_url, timeout=10)
+ if module_response.status_code == 200:
+ self.logger.info(f"{name}: Module set to 0 successfully")
+
+ # Restart the device to apply the template
+ self.logger.info(f"{name}: Restarting device to apply template")
+ restart_url = f"http://{ip}/cm?cmnd=Restart%201"
+ try:
+ restart_response = requests.get(restart_url, timeout=10)
+ if restart_response.status_code == 200:
+ self.logger.info(f"{name}: Device restart initiated successfully")
+ template_updated = True
+ else:
+ self.logger.error(f"{name}: Failed to restart device: HTTP {restart_response.status_code}")
+ except requests.exceptions.Timeout:
+ self.logger.error(f"{name}: Timeout restarting device (10 seconds)")
+ # Even though restart timed out, it might have worked
+ self.logger.info(f"{name}: Assuming restart was successful despite timeout")
+ template_updated = True
+ except requests.exceptions.RequestException as e:
+ self.logger.error(f"{name}: Error restarting device: {str(e)}")
+ else:
+ self.logger.error(f"{name}: Failed to set module to 0: HTTP {module_response.status_code}")
+ except requests.exceptions.Timeout:
+ self.logger.error(f"{name}: Timeout setting module to 0 (10 seconds)")
+ except requests.exceptions.RequestException as e:
+ self.logger.error(f"{name}: Error setting module to 0: {str(e)}")
else:
- self.logger.error(f"{name}: Failed to set module to 0")
- else:
- self.logger.error(f"{name}: Failed to update template")
+ self.logger.error(f"{name}: Failed to update template: HTTP {response.status_code}")
+ except requests.exceptions.Timeout:
+ self.logger.error(f"{name}: Timeout updating template (10 seconds)")
+ except requests.exceptions.RequestException as e:
+ self.logger.error(f"{name}: Error updating template: {str(e)}")
else:
self.logger.debug(f"{name}: Device name '{device_name}' matches key in config_other and template matches value")
else:
@@ -651,32 +709,49 @@ class TasmotaDiscovery:
self.logger.info(f"{name}: Setting device name to: {matching_key}")
url = f"http://{ip}/cm?cmnd=DeviceName%20{matching_key}"
- response = requests.get(url, timeout=5)
- if response.status_code == 200:
- self.logger.info(f"{name}: Device name updated successfully")
-
- # Activate the template by setting module to 0 (Template module)
- self.logger.info(f"{name}: Activating template by setting module to 0")
- module_url = f"http://{ip}/cm?cmnd=Module%200"
- module_response = requests.get(module_url, timeout=5)
-
- if module_response.status_code == 200:
- self.logger.info(f"{name}: Module set to 0 successfully")
-
- # Restart the device to apply the template
- self.logger.info(f"{name}: Restarting device to apply template")
- restart_url = f"http://{ip}/cm?cmnd=Restart%201"
- restart_response = requests.get(restart_url, timeout=5)
+ try:
+ self.logger.debug(f"{name}: Setting device name with 10 second timeout")
+ response = requests.get(url, timeout=10)
+ if response.status_code == 200:
+ self.logger.info(f"{name}: Device name updated successfully")
- if restart_response.status_code == 200:
- self.logger.info(f"{name}: Device restart initiated successfully")
- template_updated = True
- else:
- self.logger.error(f"{name}: Failed to restart device")
+ # Activate the template by setting module to 0 (Template module)
+ self.logger.info(f"{name}: Activating template by setting module to 0")
+ module_url = f"http://{ip}/cm?cmnd=Module%200"
+ try:
+ module_response = requests.get(module_url, timeout=10)
+ if module_response.status_code == 200:
+ self.logger.info(f"{name}: Module set to 0 successfully")
+
+ # Restart the device to apply the template
+ self.logger.info(f"{name}: Restarting device to apply template")
+ restart_url = f"http://{ip}/cm?cmnd=Restart%201"
+ try:
+ restart_response = requests.get(restart_url, timeout=10)
+ if restart_response.status_code == 200:
+ self.logger.info(f"{name}: Device restart initiated successfully")
+ template_updated = True
+ else:
+ self.logger.error(f"{name}: Failed to restart device: HTTP {restart_response.status_code}")
+ except requests.exceptions.Timeout:
+ self.logger.error(f"{name}: Timeout restarting device (10 seconds)")
+ # Even though restart timed out, it might have worked
+ self.logger.info(f"{name}: Assuming restart was successful despite timeout")
+ template_updated = True
+ except requests.exceptions.RequestException as e:
+ self.logger.error(f"{name}: Error restarting device: {str(e)}")
+ else:
+ self.logger.error(f"{name}: Failed to set module to 0: HTTP {module_response.status_code}")
+ except requests.exceptions.Timeout:
+ self.logger.error(f"{name}: Timeout setting module to 0 (10 seconds)")
+ except requests.exceptions.RequestException as e:
+ self.logger.error(f"{name}: Error setting module to 0: {str(e)}")
else:
- self.logger.error(f"{name}: Failed to set module to 0")
- else:
- self.logger.error(f"{name}: Failed to update device name")
+ self.logger.error(f"{name}: Failed to update device name: HTTP {response.status_code}")
+ except requests.exceptions.Timeout:
+ self.logger.error(f"{name}: Timeout updating device name (10 seconds)")
+ except requests.exceptions.RequestException as e:
+ self.logger.error(f"{name}: Error updating device name: {str(e)}")
else:
# No matches found, print detailed information about what's on the device
self.logger.info(f"{name}: No matches found in config_other for either Device Name or Template")
@@ -1108,14 +1183,9 @@ class TasmotaDiscovery:
self.logger.info(f"{name}: Skipping {rule_enable_param} as it's already in config (uppercase version)")
continue
- # Check if the lowercase version (rule1) is in the config
- lowercase_rule_param = f"rule{rule_num}"
- if lowercase_rule_param in console_params:
- self.logger.info(f"{name}: Found lowercase {lowercase_rule_param} in config, will enable {rule_enable_param}")
- # Don't continue - we want to enable the rule
- else:
- self.logger.info(f"{name}: No rule definition found in config, skipping auto-enable")
- continue
+ # If we're here, it means we found a rule definition earlier and added it to rules_to_enable
+ # No need to check again if it's in console_params
+ self.logger.info(f"{name}: Will enable {rule_enable_param} for rule definition found in config")
else:
# Simple check for any version of the rule enable command
if any(p.lower() == rule_enable_param.lower() for p in console_params):
diff --git a/network_configuration.json b/network_configuration.json
index 2655006..32273e9 100644
--- a/network_configuration.json
+++ b/network_configuration.json
@@ -44,6 +44,7 @@
"PowerOnState": "3",
"SetOption1": "0",
"SetOption3": "1",
+ "SetOption4": "1",
"SetOption13": "0",
"SetOption19": "0",
"SetOption32": "8",