unifi-network-maps 1.2.4__tar.gz → 1.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/CHANGELOG.md +15 -0
  2. unifi_network_maps-1.3.1/LICENSES.md +10 -0
  3. unifi_network_maps-1.3.1/MANIFEST.in +10 -0
  4. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/PKG-INFO +83 -11
  5. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/README.md +79 -6
  6. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/pyproject.toml +13 -7
  7. unifi_network_maps-1.3.1/src/unifi_network_maps/__init__.py +1 -0
  8. unifi_network_maps-1.3.1/src/unifi_network_maps/adapters/__init__.py +1 -0
  9. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps/adapters}/config.py +7 -1
  10. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps/adapters}/unifi.py +1 -1
  11. unifi_network_maps-1.3.1/src/unifi_network_maps/assets/themes/dark.yaml +47 -0
  12. unifi_network_maps-1.3.1/src/unifi_network_maps/assets/themes/default.yaml +47 -0
  13. unifi_network_maps-1.3.1/src/unifi_network_maps/cli/__init__.py +41 -0
  14. unifi_network_maps-1.3.1/src/unifi_network_maps/cli/__main__.py +8 -0
  15. unifi_network_maps-1.3.1/src/unifi_network_maps/cli/main.py +317 -0
  16. unifi_network_maps-1.3.1/src/unifi_network_maps/io/__init__.py +1 -0
  17. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps/io}/debug.py +1 -1
  18. unifi_network_maps-1.3.1/src/unifi_network_maps/model/__init__.py +1 -0
  19. unifi_network_maps-1.3.1/src/unifi_network_maps/model/labels.py +35 -0
  20. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps/model}/lldp.py +19 -33
  21. unifi_network_maps-1.3.1/src/unifi_network_maps/model/ports.py +23 -0
  22. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps/model}/topology.py +246 -93
  23. unifi_network_maps-1.3.1/src/unifi_network_maps/render/__init__.py +1 -0
  24. unifi_network_maps-1.3.1/src/unifi_network_maps/render/lldp_md.py +254 -0
  25. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps/render}/mermaid.py +26 -16
  26. unifi_network_maps-1.3.1/src/unifi_network_maps/render/mermaid_theme.py +46 -0
  27. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps/render}/svg.py +224 -179
  28. unifi_network_maps-1.3.1/src/unifi_network_maps/render/svg_theme.py +64 -0
  29. unifi_network_maps-1.3.1/src/unifi_network_maps/render/theme.py +90 -0
  30. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/src/unifi_network_maps.egg-info/PKG-INFO +83 -11
  31. unifi_network_maps-1.3.1/src/unifi_network_maps.egg-info/SOURCES.txt +99 -0
  32. unifi_network_maps-1.3.1/src/unifi_network_maps.egg-info/entry_points.txt +2 -0
  33. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/src/unifi_network_maps.egg-info/requires.txt +1 -0
  34. unifi_network_maps-1.3.1/src/unifi_network_maps.egg-info/top_level.txt +1 -0
  35. unifi_network_maps-1.3.1/tests/test_cli.py +259 -0
  36. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/tests/test_clients.py +8 -1
  37. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/tests/test_config.py +16 -1
  38. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/tests/test_debug.py +2 -2
  39. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/tests/test_export.py +1 -1
  40. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/tests/test_groups.py +2 -2
  41. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/tests/test_labels.py +16 -1
  42. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/tests/test_lldp.py +1 -1
  43. unifi_network_maps-1.3.1/tests/test_lldp_md.py +42 -0
  44. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/tests/test_mermaid.py +7 -2
  45. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/tests/test_svg.py +21 -3
  46. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/tests/test_svg_iso.py +10 -2
  47. unifi_network_maps-1.3.1/tests/test_theme.py +39 -0
  48. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/tests/test_topology.py +52 -3
  49. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/tests/test_unifi.py +2 -2
  50. unifi_network_maps-1.2.4/LICENSES.md +0 -10
  51. unifi_network_maps-1.2.4/MANIFEST.in +0 -9
  52. unifi_network_maps-1.2.4/src/unifi_mermaid/__init__.py +0 -1
  53. unifi_network_maps-1.2.4/src/unifi_mermaid/cli.py +0 -197
  54. unifi_network_maps-1.2.4/src/unifi_mermaid/labels.py +0 -15
  55. unifi_network_maps-1.2.4/src/unifi_network_maps.egg-info/SOURCES.txt +0 -84
  56. unifi_network_maps-1.2.4/src/unifi_network_maps.egg-info/entry_points.txt +0 -2
  57. unifi_network_maps-1.2.4/src/unifi_network_maps.egg-info/top_level.txt +0 -1
  58. unifi_network_maps-1.2.4/tests/test_cli.py +0 -193
  59. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/CONTRIBUTING.md +0 -0
  60. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/LICENSE +0 -0
  61. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/RELEASING.md +0 -0
  62. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/SECURITY.md +0 -0
  63. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/setup.cfg +0 -0
  64. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/__init__.py +0 -0
  65. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/__init__.py +0 -0
  66. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/access-point.svg +0 -0
  67. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/ISOPACKS_LICENSE +0 -0
  68. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/block.svg +0 -0
  69. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/cache.svg +0 -0
  70. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/cardterminal.svg +0 -0
  71. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/cloud.svg +0 -0
  72. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/cronjob.svg +0 -0
  73. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/cube.svg +0 -0
  74. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/desktop.svg +0 -0
  75. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/diamond.svg +0 -0
  76. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/dns.svg +0 -0
  77. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/document.svg +0 -0
  78. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/firewall.svg +0 -0
  79. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/function-module.svg +0 -0
  80. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/image.svg +0 -0
  81. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/laptop.svg +0 -0
  82. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/loadbalancer.svg +0 -0
  83. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/lock.svg +0 -0
  84. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/mail.svg +0 -0
  85. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/mailmultiple.svg +0 -0
  86. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/mobiledevice.svg +0 -0
  87. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/office.svg +0 -0
  88. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/package-module.svg +0 -0
  89. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/paymentcard.svg +0 -0
  90. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/plane.svg +0 -0
  91. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/printer.svg +0 -0
  92. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/pyramid.svg +0 -0
  93. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/queue.svg +0 -0
  94. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/router.svg +0 -0
  95. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/server.svg +0 -0
  96. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/speech.svg +0 -0
  97. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/sphere.svg +0 -0
  98. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/storage.svg +0 -0
  99. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/switch-module.svg +0 -0
  100. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/tower.svg +0 -0
  101. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/truck-2.svg +0 -0
  102. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/truck.svg +0 -0
  103. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/user.svg +0 -0
  104. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/isometric/vm.svg +0 -0
  105. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/laptop.svg +0 -0
  106. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/router-network.svg +0 -0
  107. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/server-network.svg +0 -0
  108. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps}/assets/icons/server.svg +0 -0
  109. {unifi_network_maps-1.2.4/src/unifi_mermaid → unifi_network_maps-1.3.1/src/unifi_network_maps/io}/export.py +0 -0
  110. {unifi_network_maps-1.2.4 → unifi_network_maps-1.3.1}/src/unifi_network_maps.egg-info/dependency_links.txt +0 -0
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
5
5
  ## Unreleased
6
6
  - TBD.
7
7
 
8
+ ## v1.3.0
9
+ - Reorganized package into submodules (`adapters/`, `model/`, `render/`, `io/`, `cli/`).
10
+ - YAML-based theming with default + dark themes and `--theme-file`.
11
+ - CLI help now grouped by category; CLI logic split into focused helpers.
12
+ - Isometric SVG layout constants centralized; extra viewBox padding to avoid clipping.
13
+ - LLDP port index fallback matches `port_table` `ifname`/`name`.
14
+ - Added PoE/edge/device count logging and improved label ordering helpers.
15
+ - Coverage excludes asset packages; docs updated (options/groups + AI disclosure).
16
+
17
+ ## v1.2.4
18
+ - Added typed `UplinkInfo`/`PortInfo` and uplink fallback for LLDP gaps.
19
+ - Deterministic edge ordering for repeatable output.
20
+ - CI publish workflow (trusted publishing) and release docs.
21
+ - Project metadata and packaging updated for OSS readiness.
22
+
8
23
  ## v1.1.0
9
24
  - Added isometric SVG output with grid-aligned links and isometric icon set.
10
25
  - Improved port label placement and client labeling in SVG outputs.
@@ -0,0 +1,10 @@
1
+ # Third-Party Licenses
2
+
3
+ ## markmanx/isopacks (MIT)
4
+
5
+ Isometric SVG icons are vendored under `src/unifi_network_maps/assets/icons/isometric/`.
6
+ The upstream MIT license is included at:
7
+
8
+ ```
9
+ src/unifi_network_maps/assets/icons/isometric/ISOPACKS_LICENSE
10
+ ```
@@ -0,0 +1,10 @@
1
+ include LICENSE
2
+ include README.md
3
+ include CHANGELOG.md
4
+ include SECURITY.md
5
+ include CONTRIBUTING.md
6
+ include LICENSES.md
7
+ include RELEASING.md
8
+ recursive-include src/unifi_network_maps/assets/icons *.svg
9
+ recursive-include src/unifi_network_maps/assets/icons/isometric ISOPACKS_LICENSE
10
+ recursive-include src/unifi_network_maps/assets/themes *.yaml
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: unifi-network-maps
3
- Version: 1.2.4
4
- Summary: Dynamic UniFi -> Mermaid network maps
3
+ Version: 1.3.1
4
+ Summary: Dynamic UniFi -> network maps in mermaid or svg
5
5
  Author: Merlijn
6
- License: MIT
6
+ License-Expression: MIT
7
7
  Project-URL: Homepage, https://github.com/merlijntishauser/unifi-network-maps
8
8
  Project-URL: Repository, https://github.com/merlijntishauser/unifi-network-maps
9
9
  Project-URL: Issues, https://github.com/merlijntishauser/unifi-network-maps/issues
@@ -11,7 +11,6 @@ Project-URL: Changelog, https://github.com/merlijntishauser/unifi-network-maps/b
11
11
  Keywords: unifi,mermaid,network,topology,diagram,svg
12
12
  Classifier: Development Status :: 3 - Alpha
13
13
  Classifier: Intended Audience :: System Administrators
14
- Classifier: License :: OSI Approved :: MIT License
15
14
  Classifier: Operating System :: OS Independent
16
15
  Classifier: Programming Language :: Python :: 3
17
16
  Classifier: Programming Language :: Python :: 3 :: Only
@@ -23,9 +22,9 @@ Classifier: Topic :: System :: Networking
23
22
  Requires-Python: >=3.10
24
23
  Description-Content-Type: text/markdown
25
24
  License-File: LICENSE
26
- License-File: LICENSES.md
27
25
  Requires-Dist: unifi-controller-api
28
26
  Requires-Dist: python-dotenv
27
+ Requires-Dist: PyYAML
29
28
  Provides-Extra: dev
30
29
  Requires-Dist: pre-commit; extra == "dev"
31
30
  Requires-Dist: pytest; extra == "dev"
@@ -66,6 +65,12 @@ export UNIFI_PASS=********
66
65
  export UNIFI_VERIFY_SSL=false
67
66
  ```
68
67
 
68
+ Use a custom env file:
69
+
70
+ ```bash
71
+ unifi-network-maps --env-file ./site.env --stdout
72
+ ```
73
+
69
74
  ## Usage
70
75
 
71
76
  Basic map (tree layout by LLDP hops):
@@ -102,6 +107,9 @@ SVG size overrides:
102
107
 
103
108
  ```bash
104
109
  unifi-network-maps --format svg --svg-width 1400 --svg-height 900 --output ./network.svg
110
+
111
+ # LLDP tables for troubleshooting
112
+ unifi-network-maps --format lldp-md --output ./lldp.md
105
113
  ```
106
114
 
107
115
  Legend only:
@@ -135,26 +143,90 @@ git push origin vX.Y.Z
135
143
 
136
144
  See `LICENSES.md` for third-party license info.
137
145
 
146
+ ## Installation
147
+
148
+ PyPI: https://pypi.org/project/unifi-network-maps/
149
+
150
+ ```bash
151
+ pip install unifi-network-maps
152
+ ```
153
+
154
+ Then run:
155
+
156
+ ```bash
157
+ unifi-network-maps --help
158
+ ```
159
+
138
160
  ## Options
139
161
 
140
- - `--format mermaid|svg|svg-iso`: output format (default mermaid).
162
+ The CLI groups options by category (`Source`, `Functional`, `Mermaid`, `SVG`, `Output`, `Debug`).
163
+
164
+ Source:
165
+ - `--site`: override `UNIFI_SITE`.
166
+ - `--env-file`: load environment variables from a specific `.env` file.
167
+
168
+ Functional:
141
169
  - `--include-ports`: show port labels (Mermaid shows both ends; SVG shows compact labels).
170
+ - `--include-clients`: add active wired clients as leaf nodes.
171
+ - `--client-scope wired|wireless|all`: which client types to include (default wired).
142
172
  - `--only-unifi`: only include neighbors that are UniFi devices.
173
+
174
+ Mermaid:
143
175
  - `--direction LR|TB`: diagram direction for Mermaid (default TB).
144
- - `--stdout`: write output to stdout.
145
- - `--markdown`: wrap Mermaid output in a code fence.
146
176
  - `--group-by-type`: group nodes by gateway/switch/AP in Mermaid subgraphs.
147
- - `--include-clients`: add active wired clients as leaf nodes.
148
177
  - `--legend-only`: render just the legend as a separate Mermaid graph (Mermaid only).
178
+
179
+ SVG:
180
+ - `--svg-width/--svg-height`: override SVG output dimensions.
181
+ - `--theme-file`: load a YAML theme for Mermaid + SVG colors (see `examples/theme.yaml` and `examples/theme-dark.yaml`).
182
+
183
+ Output:
184
+ - `--format mermaid|svg|svg-iso|lldp-md`: output format (default mermaid).
185
+ - `--stdout`: write output to stdout.
186
+ - `--markdown`: wrap Mermaid output in a code fence.
187
+
188
+ Debug:
149
189
  - `--debug-dump`: dump gateway + sample devices to stderr for debugging.
150
190
  - `--debug-sample N`: number of non-gateway devices in debug dump (default 2).
151
- - `--svg-width/--svg-height`: override SVG output dimensions.
152
191
 
153
192
  ## Notes
154
193
 
155
194
  - Default output is top-to-bottom (TB) and rendered as a hop-based tree from the gateway(s).
156
195
  - Nodes are color-coded by type (gateway/switch/AP/client) with a sensible default palette.
157
196
  - PoE links are highlighted in blue and annotated with a power icon when detected from `port_table`.
158
- - SVG output uses vendored device glyphs from `src/unifi_mermaid/assets/icons`.
197
+ - Wireless client links render as dashed lines to indicate the last-known upstream.
198
+ - SVG output uses vendored device glyphs from `src/unifi_network_maps/assets/icons`.
159
199
  - Isometric SVG output uses MIT-licensed icons from `markmanx/isopacks`.
160
200
  - SVG port labels render inside child nodes for readability.
201
+
202
+ ## AI Disclosure
203
+
204
+ This project used OpenAI Codex as a coding assistant for portions of the implementation and documentation.
205
+
206
+ ## Theme file
207
+
208
+ Example theme YAML (override only the values you want):
209
+
210
+ ```yaml
211
+ mermaid:
212
+ nodes:
213
+ gateway:
214
+ fill: "#ffe3b3"
215
+ stroke: "#d98300"
216
+ poe_link: "#1e88e5"
217
+ svg:
218
+ links:
219
+ standard:
220
+ from: "#2ecc71"
221
+ to: "#1b8f4a"
222
+ poe:
223
+ from: "#1e88e5"
224
+ to: "#0d47a1"
225
+ nodes:
226
+ switch:
227
+ from: "#d6ecff"
228
+ to: "#b6dcff"
229
+ ```
230
+
231
+ The built-in themes live at `src/unifi_network_maps/assets/themes/default.yaml` and
232
+ `src/unifi_network_maps/assets/themes/dark.yaml`.
@@ -31,6 +31,12 @@ export UNIFI_PASS=********
31
31
  export UNIFI_VERIFY_SSL=false
32
32
  ```
33
33
 
34
+ Use a custom env file:
35
+
36
+ ```bash
37
+ unifi-network-maps --env-file ./site.env --stdout
38
+ ```
39
+
34
40
  ## Usage
35
41
 
36
42
  Basic map (tree layout by LLDP hops):
@@ -67,6 +73,9 @@ SVG size overrides:
67
73
 
68
74
  ```bash
69
75
  unifi-network-maps --format svg --svg-width 1400 --svg-height 900 --output ./network.svg
76
+
77
+ # LLDP tables for troubleshooting
78
+ unifi-network-maps --format lldp-md --output ./lldp.md
70
79
  ```
71
80
 
72
81
  Legend only:
@@ -100,26 +109,90 @@ git push origin vX.Y.Z
100
109
 
101
110
  See `LICENSES.md` for third-party license info.
102
111
 
112
+ ## Installation
113
+
114
+ PyPI: https://pypi.org/project/unifi-network-maps/
115
+
116
+ ```bash
117
+ pip install unifi-network-maps
118
+ ```
119
+
120
+ Then run:
121
+
122
+ ```bash
123
+ unifi-network-maps --help
124
+ ```
125
+
103
126
  ## Options
104
127
 
105
- - `--format mermaid|svg|svg-iso`: output format (default mermaid).
128
+ The CLI groups options by category (`Source`, `Functional`, `Mermaid`, `SVG`, `Output`, `Debug`).
129
+
130
+ Source:
131
+ - `--site`: override `UNIFI_SITE`.
132
+ - `--env-file`: load environment variables from a specific `.env` file.
133
+
134
+ Functional:
106
135
  - `--include-ports`: show port labels (Mermaid shows both ends; SVG shows compact labels).
136
+ - `--include-clients`: add active wired clients as leaf nodes.
137
+ - `--client-scope wired|wireless|all`: which client types to include (default wired).
107
138
  - `--only-unifi`: only include neighbors that are UniFi devices.
139
+
140
+ Mermaid:
108
141
  - `--direction LR|TB`: diagram direction for Mermaid (default TB).
109
- - `--stdout`: write output to stdout.
110
- - `--markdown`: wrap Mermaid output in a code fence.
111
142
  - `--group-by-type`: group nodes by gateway/switch/AP in Mermaid subgraphs.
112
- - `--include-clients`: add active wired clients as leaf nodes.
113
143
  - `--legend-only`: render just the legend as a separate Mermaid graph (Mermaid only).
144
+
145
+ SVG:
146
+ - `--svg-width/--svg-height`: override SVG output dimensions.
147
+ - `--theme-file`: load a YAML theme for Mermaid + SVG colors (see `examples/theme.yaml` and `examples/theme-dark.yaml`).
148
+
149
+ Output:
150
+ - `--format mermaid|svg|svg-iso|lldp-md`: output format (default mermaid).
151
+ - `--stdout`: write output to stdout.
152
+ - `--markdown`: wrap Mermaid output in a code fence.
153
+
154
+ Debug:
114
155
  - `--debug-dump`: dump gateway + sample devices to stderr for debugging.
115
156
  - `--debug-sample N`: number of non-gateway devices in debug dump (default 2).
116
- - `--svg-width/--svg-height`: override SVG output dimensions.
117
157
 
118
158
  ## Notes
119
159
 
120
160
  - Default output is top-to-bottom (TB) and rendered as a hop-based tree from the gateway(s).
121
161
  - Nodes are color-coded by type (gateway/switch/AP/client) with a sensible default palette.
122
162
  - PoE links are highlighted in blue and annotated with a power icon when detected from `port_table`.
123
- - SVG output uses vendored device glyphs from `src/unifi_mermaid/assets/icons`.
163
+ - Wireless client links render as dashed lines to indicate the last-known upstream.
164
+ - SVG output uses vendored device glyphs from `src/unifi_network_maps/assets/icons`.
124
165
  - Isometric SVG output uses MIT-licensed icons from `markmanx/isopacks`.
125
166
  - SVG port labels render inside child nodes for readability.
167
+
168
+ ## AI Disclosure
169
+
170
+ This project used OpenAI Codex as a coding assistant for portions of the implementation and documentation.
171
+
172
+ ## Theme file
173
+
174
+ Example theme YAML (override only the values you want):
175
+
176
+ ```yaml
177
+ mermaid:
178
+ nodes:
179
+ gateway:
180
+ fill: "#ffe3b3"
181
+ stroke: "#d98300"
182
+ poe_link: "#1e88e5"
183
+ svg:
184
+ links:
185
+ standard:
186
+ from: "#2ecc71"
187
+ to: "#1b8f4a"
188
+ poe:
189
+ from: "#1e88e5"
190
+ to: "#0d47a1"
191
+ nodes:
192
+ switch:
193
+ from: "#d6ecff"
194
+ to: "#b6dcff"
195
+ ```
196
+
197
+ The built-in themes live at `src/unifi_network_maps/assets/themes/default.yaml` and
198
+ `src/unifi_network_maps/assets/themes/dark.yaml`.
@@ -4,17 +4,17 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "unifi-network-maps"
7
- version = "1.2.4"
8
- description = "Dynamic UniFi -> Mermaid network maps"
7
+ version = "1.3.1"
8
+ description = "Dynamic UniFi -> network maps in mermaid or svg"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
11
- license = { text = "MIT" }
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
12
13
  authors = [{ name = "Merlijn" }]
13
14
  keywords = ["unifi", "mermaid", "network", "topology", "diagram", "svg"]
14
15
  classifiers = [
15
16
  "Development Status :: 3 - Alpha",
16
17
  "Intended Audience :: System Administrators",
17
- "License :: OSI Approved :: MIT License",
18
18
  "Operating System :: OS Independent",
19
19
  "Programming Language :: Python :: 3",
20
20
  "Programming Language :: Python :: 3 :: Only",
@@ -27,6 +27,7 @@ classifiers = [
27
27
  dependencies = [
28
28
  "unifi-controller-api",
29
29
  "python-dotenv",
30
+ "PyYAML",
30
31
  ]
31
32
 
32
33
  [project.urls]
@@ -44,7 +45,7 @@ dev = [
44
45
  ]
45
46
 
46
47
  [project.scripts]
47
- unifi-network-maps = "unifi_mermaid.cli:main"
48
+ unifi-network-maps = "unifi_network_maps.cli:main"
48
49
 
49
50
  [tool.ruff]
50
51
  line-length = 100
@@ -59,10 +60,15 @@ line-ending = "lf"
59
60
 
60
61
  [tool.pytest.ini_options]
61
62
  testpaths = ["tests"]
63
+ norecursedirs = ["src/unifi_network_maps/assets"]
62
64
 
63
65
  [tool.coverage.run]
64
66
  branch = true
65
- source = ["unifi_mermaid"]
67
+ source = ["unifi_network_maps"]
68
+ omit = [
69
+ "src/unifi_network_maps/assets/*",
70
+ "src/unifi_network_maps/assets/**",
71
+ ]
66
72
 
67
73
  [tool.coverage.report]
68
74
  show_missing = true
@@ -71,7 +77,7 @@ show_missing = true
71
77
  package-dir = {"" = "src"}
72
78
 
73
79
  [tool.setuptools.package-data]
74
- "unifi_mermaid" = [
80
+ "unifi_network_maps" = [
75
81
  "assets/icons/*.svg",
76
82
  "assets/icons/isometric/*.svg",
77
83
  "assets/icons/isometric/ISOPACKS_LICENSE",
@@ -0,0 +1 @@
1
+ __version__ = "1.3.1"
@@ -0,0 +1 @@
1
+ """Package module."""
@@ -26,7 +26,13 @@ class Config:
26
26
  verify_ssl: bool
27
27
 
28
28
  @classmethod
29
- def from_env(cls) -> Config:
29
+ def from_env(cls, *, env_file: str | None = None) -> Config:
30
+ if env_file:
31
+ try:
32
+ from dotenv import load_dotenv
33
+ except ImportError:
34
+ raise ValueError("python-dotenv required for --env-file") from None
35
+ load_dotenv(dotenv_path=env_file)
30
36
  url = os.environ.get("UNIFI_URL", "").strip()
31
37
  site = os.environ.get("UNIFI_SITE", "default").strip()
32
38
  user = os.environ.get("UNIFI_USER", "").strip()
@@ -20,7 +20,7 @@ logger = logging.getLogger(__name__)
20
20
 
21
21
 
22
22
  def _cache_dir() -> Path:
23
- return Path(os.environ.get("UNIFI_CACHE_DIR", ".cache/unifi_mermaid"))
23
+ return Path(os.environ.get("UNIFI_CACHE_DIR", ".cache/unifi_network_maps"))
24
24
 
25
25
 
26
26
  def _cache_ttl_seconds() -> int:
@@ -0,0 +1,47 @@
1
+ mermaid:
2
+ nodes:
3
+ gateway:
4
+ fill: "#5c3b00"
5
+ stroke: "#ffb347"
6
+ switch:
7
+ fill: "#0f2b3d"
8
+ stroke: "#5dade2"
9
+ ap:
10
+ fill: "#0f3b2d"
11
+ stroke: "#2ecc71"
12
+ client:
13
+ fill: "#2b1f3b"
14
+ stroke: "#b084ff"
15
+ other:
16
+ fill: "#2a2a2a"
17
+ stroke: "#9e9e9e"
18
+ poe_link: "#64b5f6"
19
+ poe_link_width: 2
20
+ poe_link_arrow: "none"
21
+ standard_link: "#66bb6a"
22
+ standard_link_width: 2
23
+ standard_link_arrow: "none"
24
+ svg:
25
+ links:
26
+ standard:
27
+ from: "#66bb6a"
28
+ to: "#2e7d32"
29
+ poe:
30
+ from: "#64b5f6"
31
+ to: "#1e88e5"
32
+ nodes:
33
+ gateway:
34
+ from: "#5c3b00"
35
+ to: "#3e2a00"
36
+ switch:
37
+ from: "#0f2b3d"
38
+ to: "#0a1f2c"
39
+ ap:
40
+ from: "#0f3b2d"
41
+ to: "#0b2a20"
42
+ client:
43
+ from: "#2b1f3b"
44
+ to: "#20162b"
45
+ other:
46
+ from: "#2a2a2a"
47
+ to: "#1f1f1f"
@@ -0,0 +1,47 @@
1
+ mermaid:
2
+ nodes:
3
+ gateway:
4
+ fill: "#ffe3b3"
5
+ stroke: "#d98300"
6
+ switch:
7
+ fill: "#d6ecff"
8
+ stroke: "#3a7bd5"
9
+ ap:
10
+ fill: "#d7f5e7"
11
+ stroke: "#27ae60"
12
+ client:
13
+ fill: "#f2e5ff"
14
+ stroke: "#7f3fbf"
15
+ other:
16
+ fill: "#eeeeee"
17
+ stroke: "#8f8f8f"
18
+ poe_link: "#1e88e5"
19
+ poe_link_width: 2
20
+ poe_link_arrow: "none"
21
+ standard_link: "#2ecc71"
22
+ standard_link_width: 2
23
+ standard_link_arrow: "none"
24
+ svg:
25
+ links:
26
+ standard:
27
+ from: "#2ecc71"
28
+ to: "#1b8f4a"
29
+ poe:
30
+ from: "#1e88e5"
31
+ to: "#0d47a1"
32
+ nodes:
33
+ gateway:
34
+ from: "#ffe3b3"
35
+ to: "#f7c77b"
36
+ switch:
37
+ from: "#d6ecff"
38
+ to: "#b6dcff"
39
+ ap:
40
+ from: "#d7f5e7"
41
+ to: "#b8f0d2"
42
+ client:
43
+ from: "#f2e5ff"
44
+ to: "#e0c9ff"
45
+ other:
46
+ from: "#eeeeee"
47
+ to: "#d7d7d7"
@@ -0,0 +1,41 @@
1
+ """CLI package facade."""
2
+
3
+ from .main import (
4
+ Config,
5
+ SvgOptions,
6
+ build_client_edges,
7
+ build_device_index,
8
+ build_node_type_map,
9
+ build_topology,
10
+ debug_dump_devices,
11
+ fetch_clients,
12
+ fetch_devices,
13
+ group_devices_by_type,
14
+ main,
15
+ normalize_devices,
16
+ render_legend,
17
+ render_mermaid,
18
+ render_svg,
19
+ resolve_themes,
20
+ write_output,
21
+ )
22
+
23
+ __all__ = [
24
+ "Config",
25
+ "SvgOptions",
26
+ "build_client_edges",
27
+ "build_device_index",
28
+ "build_node_type_map",
29
+ "build_topology",
30
+ "debug_dump_devices",
31
+ "fetch_clients",
32
+ "fetch_devices",
33
+ "group_devices_by_type",
34
+ "main",
35
+ "normalize_devices",
36
+ "render_legend",
37
+ "render_mermaid",
38
+ "render_svg",
39
+ "resolve_themes",
40
+ "write_output",
41
+ ]
@@ -0,0 +1,8 @@
1
+ """CLI module entry point."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from .main import main
6
+
7
+ if __name__ == "__main__":
8
+ raise SystemExit(main())