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
258 lines
17 KiB
Plaintext
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",
|