Metadata-Version: 2.4
Name: unifi-topology
Version: 1.3.1
Summary: Python library for UniFi network topology discovery and SVG rendering
Author: Merlijn Tishauser
License-Expression: MIT
Project-URL: Homepage, https://github.com/merlijntishauser/unifi-topology
Project-URL: Repository, https://github.com/merlijntishauser/unifi-topology
Project-URL: Issues, https://github.com/merlijntishauser/unifi-topology/issues
Project-URL: Changelog, https://github.com/merlijntishauser/unifi-topology/blob/main/CHANGELOG.md
Keywords: unifi,network,topology,diagram,svg
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Home Automation
Classifier: Topic :: System :: Networking
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests<3,>=2.31
Requires-Dist: python-dotenv<2,>=1.0
Requires-Dist: PyYAML<7,>=6.0
Requires-Dist: dnspython<3,>=2.7
Requires-Dist: Jinja2<4,>=3.1
Provides-Extra: dev
Requires-Dist: Faker==40.11.0; extra == "dev"
Requires-Dist: pre-commit==4.5.1; extra == "dev"
Requires-Dist: pytest==9.0.2; extra == "dev"
Requires-Dist: pytest-cov==7.0.0; extra == "dev"
Requires-Dist: pyright==1.1.408; extra == "dev"
Requires-Dist: radon==6.0.1; extra == "dev"
Requires-Dist: ruff==0.15.6; extra == "dev"
Requires-Dist: xenon==0.9.3; extra == "dev"
Requires-Dist: pip-audit==2.10.0; extra == "dev"
Provides-Extra: docs
Requires-Dist: mkdocs-material==9.7.5; extra == "docs"
Requires-Dist: mkdocstrings[python]==1.0.3; extra == "docs"
Dynamic: license-file

# unifi-topology

[![CI](https://github.com/merlijntishauser/unifi-topology/actions/workflows/ci.yml/badge.svg)](https://github.com/merlijntishauser/unifi-topology/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/unifi-topology)](https://pypi.org/project/unifi-topology/)
[![PyPI - Downloads](https://img.shields.io/pypi/dw/unifi-topology)](https://pypi.org/project/unifi-topology/)
[![Python](https://img.shields.io/pypi/pyversions/unifi-topology)](https://pypi.org/project/unifi-topology/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

Python library for UniFi network topology discovery and SVG diagram rendering.

Extracted from [unifi-network-maps](https://github.com/merlijntishauser/unifi-network-maps) to provide a clean library API for programmatic use, including the [Home Assistant integration](https://github.com/merlijntishauser/unifi-network-maps-ha).

## Installation

```bash
pip install unifi-topology
```

## Quick Start

```python
from unifi_topology import (
    Config,
    SvgOptions,
    build_node_type_map,
    build_topology,
    extract_wan_info,
    fetch_devices,
    fetch_networks,
    normalize_devices,
    render_svg,
    resolve_svg_themes,
)

# Connect to UniFi controller
config = Config.from_env()
api_devices = fetch_devices(config)
networks = fetch_networks(config)

# Build topology model
devices = normalize_devices(api_devices)
node_types = build_node_type_map(devices)
gateways = [name for name, node_type in node_types.items() if node_type == "gateway"]
topology = build_topology(
    devices,
    include_ports=True,
    only_unifi=False,
    gateways=gateways,
)
gateway = next((device for device in devices if node_types.get(device.name) == "gateway"), None)
wan_info = extract_wan_info(gateway) if gateway else None

# Render SVG
theme = resolve_svg_themes(theme_name="unifi")
options = SvgOptions()
svg = render_svg(
    topology.tree_edges or topology.raw_edges,
    node_types=node_types,
    theme=theme,
    options=options,
    wan_info=wan_info,
)
```

## API Overview

### Adapters

- `Config` -- Configuration from environment variables (`UNIFI_URL`, `UNIFI_USER`, `UNIFI_PASS`, etc.)
- `fetch_devices(config)` -- Fetch device list from UniFi controller
- `fetch_clients(config)` -- Fetch active clients
- `fetch_networks(config)` -- Fetch network/VLAN configuration
- `fetch_firewall_zones(config)` -- Fetch firewall zone definitions
- `fetch_firewall_policies(config)` -- Fetch zone-based firewall policies
- `fetch_firewall_groups(config)` -- Fetch firewall address/port groups
- `resolve_hostnames(ips, dns_server)` -- Reverse DNS resolution

### Model

- `normalize_devices(raw)` -- Convert raw API data to `Device` objects
- `normalize_firewall_zones(raw)` -- Convert raw zone data to `FirewallZone` objects
- `normalize_firewall_policies(raw)` -- Convert raw policy data to `FirewallPolicy` objects
- `normalize_firewall_groups(raw)` -- Convert raw group data to `FirewallGroup` objects
- `build_node_type_map(devices, clients=None, ...)` -- Classify node names for rendering
- `build_topology(devices, *, include_ports, only_unifi, gateways)` -- Build topology graph (`TopologyResult` with `raw_edges` and `tree_edges`)
- `build_device_inventory(devices)` -- Build device info table (`list[DeviceInfo]`)
- `extract_wan_info(device, ...)` -- Extract WAN upstream info for a gateway device

### Rendering

- `render_svg(edges, *, node_types, theme, options, ...)` -- Orthogonal SVG diagram
- `render_svg_isometric(edges, *, node_types, theme, options, ...)` -- Isometric 3D-style SVG
- `render_dual(edges, *, node_types, theme, options, ...)` -- Physical + VLAN grouped SVG output
- `resolve_svg_themes(theme_name, theme_file)` -- Load built-in or custom SVG theme

Built-in themes: `unifi`, `unifi-dark`, `minimal`, `minimal-dark`, `classic`, `classic-dark`

## Development

```bash
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

make lint        # ruff check
make format      # ruff format
make typecheck   # pyright
make test        # pytest
make ci          # all checks
```

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.

## License

MIT -- see [LICENSE](LICENSE). Third-party licenses in [LICENSES.md](LICENSES.md).
