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. |