TasmotaManager/self_reported_hostname_locations.md
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

160 lines
7.9 KiB
Markdown

# Places That Look for Device Self-Reported Hostname
This document identifies all places in the TasmotaManager codebase that look for device self-reported hostnames.
## 1. `is_hostname_unknown` Function (Lines 260-362)
**Purpose**: Checks if a hostname matches any pattern in unknown_device_patterns, with special handling for the Unifi Hostname bug.
**How it retrieves self-reported hostname**:
- Makes an HTTP request to the device using `http://{ip}/cm?cmnd=Status%205` (line 315)
- Extracts the hostname from the response using `status_data.get('StatusNET', {}).get('Hostname', '')` (line 323)
- Compares the self-reported hostname against unknown patterns (lines 328-334)
- If the UniFi-reported hostname matches unknown patterns but the self-reported hostname doesn't, it detects the UniFi OS hostname bug (lines 336-348)
**Code snippet**:
```python
# Get the device's self-reported hostname
url = f"http://{ip}/cm?cmnd=Status%205"
response = requests.get(url, timeout=5)
# Try to parse the JSON response
if response.status_code == 200:
try:
status_data = response.json()
# Extract the hostname from the response
device_reported_hostname = status_data.get('StatusNET', {}).get('Hostname', '')
if device_reported_hostname:
self.logger.debug(f"Device self-reported hostname: {device_reported_hostname}")
# Check if the self-reported hostname also matches unknown patterns
device_hostname_matches_unknown = False
for pattern in patterns:
if self._match_pattern(device_reported_hostname.lower(), pattern, match_entire_string=False):
device_hostname_matches_unknown = True
self.logger.debug(f"Device's self-reported hostname '{device_reported_hostname}' matches unknown pattern: {pattern}")
break
```
## 2. `get_tasmota_devices` Method (Lines 480-537)
**Purpose**: Part of the device discovery process when scanning the network. Checks for the UniFi OS hostname bug.
**How it retrieves self-reported hostname**:
- Makes an HTTP request to the device using `http://{device_ip}/cm?cmnd=Status%205` (line 501)
- Extracts the hostname from the response using `status_data.get('StatusNET', {}).get('Hostname', '')` (line 509)
- Checks if the self-reported hostname also matches unknown patterns (lines 514-527)
- If the UniFi-reported name matches unknown patterns but the device's self-reported name doesn't, it sets the `unifi_hostname_bug_detected` flag to `True` (lines 529-533)
**Code snippet**:
```python
# Get the device's self-reported hostname
url = f"http://{device_ip}/cm?cmnd=Status%205"
response = requests.get(url, timeout=5)
# Try to parse the JSON response
if response.status_code == 200:
try:
status_data = response.json()
# Extract the hostname from the response
device_reported_hostname = status_data.get('StatusNET', {}).get('Hostname', '')
if device_reported_hostname:
self.logger.debug(f"Device self-reported hostname: {device_reported_hostname}")
# Check if the self-reported hostname also matches unknown patterns
device_hostname_matches_unknown = False
for pattern in unknown_patterns:
# ... pattern matching code ...
if re.match(regex_pattern, device_reported_hostname.lower()):
device_hostname_matches_unknown = True
self.logger.debug(f"Device's self-reported hostname '{device_reported_hostname}' matches unknown pattern: {pattern}")
break
```
## 3. `process_single_device` Method (Lines 1780-1841)
**Purpose**: Processes a single device by hostname or IP address. Checks the device's self-reported hostname before declaring it as unknown.
**How it retrieves self-reported hostname**:
- Makes an HTTP request to the device using `http://{device_ip}/cm?cmnd=Status%205` (line 1791)
- Extracts the hostname from the response using `status_data.get('StatusNET', {}).get('Hostname', '')` (line 1799)
- Checks if the self-reported hostname also matches unknown patterns (lines 1804-1817)
- Makes a decision based on whether both the UniFi-reported and self-reported hostnames match unknown patterns:
- If both match, the device is declared as unknown (lines 1820-1822)
- If the UniFi-reported hostname matches but the self-reported hostname doesn't, the device is NOT declared as unknown, and it's considered a possible UniFi OS bug (lines 1823-1825)
- If no self-reported hostname is found or there's an error, it falls back to using the UniFi-reported name (lines 1826-1841)
**Code snippet**:
```python
# Get the device's self-reported hostname
url = f"http://{device_ip}/cm?cmnd=Status%205"
response = requests.get(url, timeout=5)
# Try to parse the JSON response
if response.status_code == 200:
try:
status_data = response.json()
# Extract the hostname from the response
device_reported_hostname = status_data.get('StatusNET', {}).get('Hostname', '')
if device_reported_hostname:
self.logger.info(f"Device self-reported hostname: {device_reported_hostname}")
# Check if the self-reported hostname also matches unknown patterns
device_hostname_matches_unknown = False
for pattern in unknown_patterns:
# ... pattern matching code ...
if re.match(regex_pattern, device_reported_hostname.lower()):
device_hostname_matches_unknown = True
self.logger.info(f"Device's self-reported hostname '{device_reported_hostname}' matches unknown pattern: {pattern}")
break
# Only declare as unknown if both UniFi-reported and self-reported hostnames match unknown patterns
if device_hostname_matches_unknown:
is_unknown = True
self.logger.info("Device declared as unknown: both UniFi-reported and self-reported hostnames match unknown patterns")
else:
is_unknown = False
self.logger.info("Device NOT declared as unknown: self-reported hostname doesn't match unknown patterns (possible UniFi OS bug)")
```
## 4. Device Details Collection (Lines 2068-2092)
**Purpose**: Collects general device information, including the hostname, as part of checking device details and updating settings if needed.
**How it retrieves hostname information**:
- Makes an HTTP request to the device using `http://{ip}/cm?cmnd=Status%205` (line 2069)
- Extracts the hostname from the response using `network_data.get("StatusNET", {}).get("Hostname", "Unknown")` (line 2092)
- Stores the hostname in a device_detail dictionary
**Code snippet**:
```python
# Get Status 5 for network info
url_network = f"http://{ip}/cm?cmnd=Status%205"
response = requests.get(url_network, timeout=5)
network_data = response.json()
# ... other code ...
device_detail = {
# ... other fields ...
"hostname": network_data.get("StatusNET", {}).get("Hostname", "Unknown"),
# ... other fields ...
}
```
## Summary
The TasmotaManager codebase looks for device self-reported hostnames in four main places:
1. **`is_hostname_unknown` Function**: Specifically handles the Unifi Hostname bug by checking if the self-reported hostname matches unknown patterns.
2. **`get_tasmota_devices` Method**: Checks for the UniFi OS hostname bug during device discovery.
3. **`process_single_device` Method**: Checks the device's self-reported hostname before declaring it as unknown when processing a single device.
4. **Device Details Collection**: Retrieves the hostname as part of gathering general device information.
The first three locations specifically deal with the Unifi Hostname bug, where UniFi OS might not keep track of updated hostnames. By checking the device's self-reported hostname, the code can determine if the device actually has a real hostname that UniFi is not showing correctly.