Add hostname resolution and fix UTF-8 encoding issues

This commit is contained in:
2025-12-30 23:51:53 +11:00
parent 44b6662507
commit 248d7b52fe

View File

@@ -6,6 +6,7 @@ Helps discover devices on the network and manage MAC-based internet blocking
import requests
import json
import socket
from typing import List, Dict
from urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
@@ -44,6 +45,15 @@ class OPNsenseDeviceManager:
print(f"Error making request to {endpoint}: {e}")
return None
def _get_hostname(self, ip: str) -> str:
"""Try to resolve hostname from IP address"""
try:
hostname, _, _ = socket.gethostbyaddr(ip)
return hostname
except (socket.herror, socket.gaierror, socket.timeout):
return ""
def discover_devices(self) -> List[Dict]:
"""Discover all devices from ARP table"""
result = self._make_request("diagnostics/interface/getArp")
@@ -72,20 +82,30 @@ class OPNsenseDeviceManager:
seen_macs.add(mac)
# Try to get hostname
hostname = self._get_hostname(ip)
device_info = {
'mac': mac,
'ip': ip,
'hostname': hostname,
'manufacturer': manufacturer,
'intf_description': entry.get('intf_description', 'LAN'),
'suggested_name': self._suggest_device_name(manufacturer, ip)
'suggested_name': self._suggest_device_name(manufacturer, ip, hostname)
}
devices.append(device_info)
return sorted(devices, key=lambda x: x['ip'])
def _suggest_device_name(self, manufacturer: str, ip: str) -> str:
"""Suggest a device name based on manufacturer"""
def _suggest_device_name(self, manufacturer: str, ip: str, hostname: str = "") -> str:
"""Suggest a device name based on manufacturer and hostname"""
# If we have a hostname, use it
if hostname:
# Clean up hostname (remove domain suffix if present)
clean_hostname = hostname.split('.')[0]
return clean_hostname
manufacturer = manufacturer.lower()
if 'apple' in manufacturer:
@@ -215,6 +235,8 @@ class OPNsenseDeviceManager:
for device in device_list:
report += f" MAC: {device['mac']}\n"
report += f" IP: {device['ip']}\n"
if device['hostname']:
report += f" Hostname: {device['hostname']}\n"
report += f" Suggested Name: {device['suggested_name']}\n"
report += "\n"
@@ -225,14 +247,16 @@ class OPNsenseDeviceManager:
"""Export devices in a format easy to copy into Home Assistant"""
devices = self.discover_devices()
with open(output_file, 'w') as f:
with open(output_file, 'w', encoding='utf-8') as f:
f.write("# Copy these MAC addresses into your Home Assistant input_text entities\n")
f.write("# Format: device_name | MAC Address | IP | Manufacturer\n\n")
f.write("# Format: device_name | MAC Address | IP | Hostname | Manufacturer\n\n")
for device in devices:
hostname = device['hostname'] if device['hostname'] else "N/A"
f.write(f"{device['suggested_name']:<40} | "
f"{device['mac']:<20} | "
f"{device['ip']:<15} | "
f"{hostname:<30} | "
f"{device['manufacturer']}\n")
print(f"Device list exported to: {output_file}")
@@ -272,6 +296,8 @@ def main():
print(f"{idx}. {device['suggested_name']}")
print(f" MAC: {device['mac']}")
print(f" IP: {device['ip']}")
if device['hostname']:
print(f" Hostname: {device['hostname']}")
print(f" Manufacturer: {device['manufacturer']}")
print()
@@ -281,7 +307,7 @@ def main():
save = input("Save report to file? (y/n): ").strip().lower()
if save == 'y':
with open('device_report.txt', 'w') as f:
with open('device_report.txt', 'w', encoding='utf-8') as f:
f.write(report)
print("Report saved to: device_report.txt")