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
144 lines
6.9 KiB
Markdown
144 lines
6.9 KiB
Markdown
# Analysis of unknown_device_patterns Checks in TasmotaManager.py
|
|
|
|
This document identifies and analyzes all places in the TasmotaManager.py script where checks against `unknown_device_patterns` are performed.
|
|
|
|
## Summary
|
|
|
|
The script performs checks against `unknown_device_patterns` in 4 distinct places:
|
|
|
|
1. In the `get_tasmota_devices` function during device discovery
|
|
2. In the `get_unknown_devices` function when identifying unknown devices for processing
|
|
3. In the `process_single_device` function when processing a single device
|
|
4. In the `process_devices` function when filtering devices for MQTT configuration
|
|
|
|
## Detailed Analysis
|
|
|
|
### 1. In `get_tasmota_devices` function (lines 235-244 and 269-276)
|
|
|
|
**Purpose**: During device discovery, this function checks if devices match unknown patterns in two ways:
|
|
- First, it checks if the device's name or hostname as reported by UniFi matches any unknown patterns
|
|
- Second, if there's a match, it checks if the device's self-reported hostname also matches unknown patterns
|
|
|
|
**Context**: This is part of the initial device discovery process when scanning the network. The function sets a flag `unifi_hostname_bug_detected` if the UniFi-reported name matches unknown patterns but the device's self-reported hostname doesn't (indicating a possible UniFi OS bug).
|
|
|
|
**Code snippet**:
|
|
```python
|
|
# Check if device name or hostname matches unknown patterns
|
|
unifi_name_matches_unknown = False
|
|
for pattern in unknown_patterns:
|
|
pattern_lower = pattern.lower()
|
|
pattern_regex = pattern_lower.replace('.', r'\.').replace('*', '.*')
|
|
if (re.match(f"^{pattern_regex}", device_name.lower()) or
|
|
re.match(f"^{pattern_regex}", device_hostname.lower())):
|
|
unifi_name_matches_unknown = True
|
|
self.logger.debug(f"Device {device_name} matches unknown device pattern: {pattern}")
|
|
break
|
|
|
|
# If the name matches unknown patterns, check the device's self-reported hostname
|
|
if unifi_name_matches_unknown and device_ip:
|
|
# ... [code to get device's self-reported hostname] ...
|
|
|
|
# Check if the self-reported hostname also matches unknown patterns
|
|
device_hostname_matches_unknown = False
|
|
for pattern in unknown_patterns:
|
|
pattern_lower = pattern.lower()
|
|
pattern_regex = pattern_lower.replace('.', r'\.').replace('*', '.*')
|
|
if re.match(f"^{pattern_regex}", 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
|
|
```
|
|
|
|
### 2. In `get_unknown_devices` function (lines 500-506)
|
|
|
|
**Purpose**: Specifically identifies devices that match unknown_device_patterns from current.json.
|
|
|
|
**Context**: This function is used when processing unknown devices to set them up with proper names and MQTT settings. It's called by the `process_unknown_devices` function, which is triggered by the `--process-unknown` command-line argument.
|
|
|
|
**Code snippet**:
|
|
```python
|
|
for device in all_devices:
|
|
name = device.get('name', '').lower()
|
|
hostname = device.get('hostname', '').lower()
|
|
|
|
for pattern in unknown_patterns:
|
|
pattern = pattern.lower()
|
|
pattern = pattern.replace('.', r'\.').replace('*', '.*')
|
|
if re.match(f"^{pattern}", name) or re.match(f"^{pattern}", hostname):
|
|
self.logger.debug(f"Found unknown device: {name} ({hostname})")
|
|
unknown_devices.append(device)
|
|
break
|
|
```
|
|
|
|
### 3. In `process_single_device` function (lines 1526-1533 and 1559-1567)
|
|
|
|
**Purpose**: When processing a single device by IP or hostname, this function checks if it matches unknown patterns in two ways:
|
|
- First, it checks if the device's name or hostname as reported by UniFi matches any unknown patterns
|
|
- Second, if there's a match, it checks if the device's self-reported hostname also matches unknown patterns
|
|
|
|
**Context**: This function is used in Device mode (triggered by the `--Device` command-line argument) to determine if a specific device should be treated as unknown. If both the UniFi-reported name and the device's self-reported hostname match unknown patterns, the device is declared as unknown.
|
|
|
|
**Code snippet**:
|
|
```python
|
|
# Initialize variables for hostname bug detection
|
|
unifi_name_matches_unknown = False
|
|
device_hostname_matches_unknown = False
|
|
for pattern in unknown_patterns:
|
|
pattern_lower = pattern.lower()
|
|
pattern_regex = pattern_lower.replace('.', r'\.').replace('*', '.*')
|
|
if (re.match(f"^{pattern_regex}", device_name.lower()) or
|
|
re.match(f"^{pattern_regex}", device_hostname.lower())):
|
|
unifi_name_matches_unknown = True
|
|
self.logger.info(f"Device {device_name} matches unknown device pattern: {pattern}")
|
|
break
|
|
|
|
# If the name matches unknown patterns, check the device's self-reported hostname
|
|
if unifi_name_matches_unknown:
|
|
# ... [code to get device's self-reported hostname] ...
|
|
|
|
# Check if the self-reported hostname also matches unknown patterns
|
|
device_hostname_matches_unknown = False
|
|
for pattern in unknown_patterns:
|
|
pattern_lower = pattern.lower()
|
|
pattern_regex = pattern_lower.replace('.', r'\.').replace('*', '.*')
|
|
if re.match(f"^{pattern_regex}", 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
|
|
```
|
|
|
|
### 4. In `process_devices` function (lines 1760-1766)
|
|
|
|
**Purpose**: Filters out devices matching unknown_device_patterns during normal processing.
|
|
|
|
**Context**: This function is used to skip unknown devices when configuring MQTT for known devices. If a device matches an unknown_device_pattern, it's skipped unless the `skip_unknown_filter` parameter is True (which happens in Device mode).
|
|
|
|
**Code snippet**:
|
|
```python
|
|
for device in all_devices:
|
|
name = device.get('name', '').lower()
|
|
hostname = device.get('hostname', '').lower()
|
|
|
|
is_unknown = False
|
|
for pattern in unknown_patterns:
|
|
pattern = pattern.lower()
|
|
pattern = pattern.replace('.', r'\.').replace('*', '.*')
|
|
if re.match(f"^{pattern}", name) or re.match(f"^{pattern}", hostname):
|
|
self.logger.debug(f"Skipping unknown device: {name} ({hostname})")
|
|
is_unknown = True
|
|
break
|
|
|
|
if not is_unknown:
|
|
devices.append(device)
|
|
```
|
|
|
|
## Conclusion
|
|
|
|
The TasmotaManager.py script performs checks against `unknown_device_patterns` in 4 distinct places, each with a specific purpose:
|
|
|
|
1. During device discovery to identify unknown devices and detect the UniFi OS hostname bug
|
|
2. When specifically looking for unknown devices to process them
|
|
3. When processing a single device to determine if it should be treated as unknown
|
|
4. When filtering devices for MQTT configuration to skip unknown devices
|
|
|
|
These checks are an important part of the script's functionality, allowing it to handle unknown devices appropriately in different contexts. |