"""Report generation for Tasmota devices.""" import logging from typing import List, Dict, Optional from datetime import datetime from utils import get_data_file_path, save_json_file, format_device_info from discovery import TasmotaDiscovery class ReportGenerator: """Generates various reports for Tasmota devices.""" def __init__(self, config: dict, discovery: TasmotaDiscovery, logger: Optional[logging.Logger] = None): """ Initialize report generator. Args: config: Configuration dictionary discovery: Discovery handler instance logger: Optional logger instance """ self.config = config self.discovery = discovery self.logger = logger or logging.getLogger(__name__) def generate_unifi_hostname_report(self) -> Dict: """ Generate a report comparing UniFi and Tasmota hostnames. Returns: dict: Report data """ self.logger.info("Generating UniFi hostname report") devices = self.discovery.get_tasmota_devices() report = { 'generated_at': datetime.now().isoformat(), 'total_devices': len(devices), 'devices': [] } for device in devices: device_ip = device.get('ip', '') device_name = device.get('name', 'Unknown') unifi_hostname = device.get('hostname', '') # Get self-reported hostname tasmota_hostname, success = self.discovery.get_device_hostname( device_ip, device_name, timeout=5 ) device_report = { 'name': device_name, 'ip': device_ip, 'mac': device.get('mac', ''), 'unifi_hostname': unifi_hostname, 'tasmota_hostname': tasmota_hostname if success else 'N/A', 'hostnames_match': tasmota_hostname == unifi_hostname if success else False, 'connection': device.get('connection', 'Unknown'), 'bug_detected': device.get('unifi_hostname_bug_detected', False) } report['devices'].append(device_report) # Save report report_file = get_data_file_path('TasmotaHostnameReport.json') save_json_file(report_file, report, self.logger) # Print summary self._print_hostname_report_summary(report) return report def _print_hostname_report_summary(self, report: Dict): """ Print a summary of the hostname report. Args: report: Report data dictionary """ print(f"\n{'='*70}") print("UniFi vs Tasmota Hostname Report") print(f"{'='*70}") print(f"Total devices: {report['total_devices']}") print(f"Generated: {report['generated_at']}") print(f"{'='*70}\n") mismatches = 0 bug_detected = 0 for device in report['devices']: if not device['hostnames_match']: mismatches += 1 if device['bug_detected']: bug_detected += 1 print(f"Hostname mismatches: {mismatches}") print(f"UniFi bug detected: {bug_detected}") print(f"\n{'='*70}") if mismatches > 0: print("\nDevices with hostname mismatches:") print(f"{'Device':<25} {'UniFi Hostname':<25} {'Tasmota Hostname':<25}") print("-" * 75) for device in report['devices']: if not device['hostnames_match']: name = device['name'][:24] unifi = device['unifi_hostname'][:24] tasmota = device['tasmota_hostname'][:24] bug = " [BUG]" if device['bug_detected'] else "" print(f"{name:<25} {unifi:<25} {tasmota:<25}{bug}") print(f"\n{'='*70}\n") def save_device_details(self, device_details: List[Dict]): """ Save detailed device information to file. Args: device_details: List of detailed device info dictionaries """ output_file = get_data_file_path('TasmotaDevices.json') # Add metadata output = { 'generated_at': datetime.now().isoformat(), 'total_devices': len(device_details), 'devices': device_details } save_json_file(output_file, output, self.logger) self.logger.info(f"Saved details for {len(device_details)} devices") def print_processing_summary(self, processed: int, mqtt_updated: int, console_updated: int, failed: int): """ Print summary of processing results. Args: processed: Number of devices processed mqtt_updated: Number with MQTT updates console_updated: Number with console updates failed: Number that failed """ print(f"\n{'='*60}") print("Processing Summary") print(f"{'='*60}") print(f"Total devices processed: {processed}") print(f"MQTT settings updated: {mqtt_updated}") print(f"Console settings applied: {console_updated}") print(f"Failed: {failed}") print(f"{'='*60}\n")