unifi-network-maps 1.2.1__tar.gz → 1.3.0__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 (108) hide show
  1. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/CHANGELOG.md +15 -0
  2. unifi_network_maps-1.3.0/LICENSES.md +10 -0
  3. unifi_network_maps-1.3.0/MANIFEST.in +10 -0
  4. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/PKG-INFO +63 -8
  5. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/README.md +60 -6
  6. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/pyproject.toml +11 -5
  7. unifi_network_maps-1.3.0/src/unifi_network_maps/__init__.py +1 -0
  8. unifi_network_maps-1.3.0/src/unifi_network_maps/adapters/__init__.py +1 -0
  9. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps/adapters}/config.py +7 -1
  10. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps/adapters}/unifi.py +1 -1
  11. unifi_network_maps-1.3.0/src/unifi_network_maps/assets/themes/dark.yaml +47 -0
  12. unifi_network_maps-1.3.0/src/unifi_network_maps/assets/themes/default.yaml +47 -0
  13. unifi_network_maps-1.3.0/src/unifi_network_maps/cli/__init__.py +41 -0
  14. unifi_network_maps-1.3.0/src/unifi_network_maps/cli/__main__.py +8 -0
  15. unifi_network_maps-1.3.0/src/unifi_network_maps/cli/main.py +281 -0
  16. unifi_network_maps-1.3.0/src/unifi_network_maps/io/__init__.py +1 -0
  17. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps/io}/debug.py +1 -1
  18. unifi_network_maps-1.3.0/src/unifi_network_maps/model/__init__.py +1 -0
  19. unifi_network_maps-1.3.0/src/unifi_network_maps/model/labels.py +35 -0
  20. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps/model}/lldp.py +19 -33
  21. unifi_network_maps-1.3.0/src/unifi_network_maps/model/ports.py +23 -0
  22. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps/model}/topology.py +216 -89
  23. unifi_network_maps-1.3.0/src/unifi_network_maps/render/__init__.py +1 -0
  24. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps/render}/mermaid.py +21 -16
  25. unifi_network_maps-1.3.0/src/unifi_network_maps/render/mermaid_theme.py +46 -0
  26. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps/render}/svg.py +208 -175
  27. unifi_network_maps-1.3.0/src/unifi_network_maps/render/svg_theme.py +64 -0
  28. unifi_network_maps-1.3.0/src/unifi_network_maps/render/theme.py +90 -0
  29. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/src/unifi_network_maps.egg-info/PKG-INFO +63 -8
  30. unifi_network_maps-1.3.0/src/unifi_network_maps.egg-info/SOURCES.txt +97 -0
  31. unifi_network_maps-1.3.0/src/unifi_network_maps.egg-info/entry_points.txt +2 -0
  32. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/src/unifi_network_maps.egg-info/requires.txt +1 -0
  33. unifi_network_maps-1.3.0/src/unifi_network_maps.egg-info/top_level.txt +1 -0
  34. unifi_network_maps-1.3.0/tests/test_cli.py +219 -0
  35. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/tests/test_clients.py +1 -1
  36. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/tests/test_config.py +16 -1
  37. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/tests/test_debug.py +2 -2
  38. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/tests/test_export.py +1 -1
  39. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/tests/test_groups.py +2 -2
  40. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/tests/test_labels.py +16 -1
  41. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/tests/test_lldp.py +1 -1
  42. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/tests/test_mermaid.py +2 -2
  43. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/tests/test_svg.py +13 -3
  44. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/tests/test_svg_iso.py +2 -2
  45. unifi_network_maps-1.3.0/tests/test_theme.py +39 -0
  46. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/tests/test_topology.py +52 -3
  47. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/tests/test_unifi.py +2 -2
  48. unifi_network_maps-1.2.1/LICENSES.md +0 -10
  49. unifi_network_maps-1.2.1/MANIFEST.in +0 -9
  50. unifi_network_maps-1.2.1/src/unifi_mermaid/__init__.py +0 -1
  51. unifi_network_maps-1.2.1/src/unifi_mermaid/cli.py +0 -197
  52. unifi_network_maps-1.2.1/src/unifi_mermaid/labels.py +0 -15
  53. unifi_network_maps-1.2.1/src/unifi_network_maps.egg-info/SOURCES.txt +0 -84
  54. unifi_network_maps-1.2.1/src/unifi_network_maps.egg-info/entry_points.txt +0 -2
  55. unifi_network_maps-1.2.1/src/unifi_network_maps.egg-info/top_level.txt +0 -1
  56. unifi_network_maps-1.2.1/tests/test_cli.py +0 -193
  57. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/CONTRIBUTING.md +0 -0
  58. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/LICENSE +0 -0
  59. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/RELEASING.md +0 -0
  60. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/SECURITY.md +0 -0
  61. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/setup.cfg +0 -0
  62. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/__init__.py +0 -0
  63. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/__init__.py +0 -0
  64. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/access-point.svg +0 -0
  65. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/ISOPACKS_LICENSE +0 -0
  66. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/block.svg +0 -0
  67. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/cache.svg +0 -0
  68. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/cardterminal.svg +0 -0
  69. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/cloud.svg +0 -0
  70. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/cronjob.svg +0 -0
  71. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/cube.svg +0 -0
  72. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/desktop.svg +0 -0
  73. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/diamond.svg +0 -0
  74. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/dns.svg +0 -0
  75. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/document.svg +0 -0
  76. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/firewall.svg +0 -0
  77. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/function-module.svg +0 -0
  78. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/image.svg +0 -0
  79. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/laptop.svg +0 -0
  80. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/loadbalancer.svg +0 -0
  81. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/lock.svg +0 -0
  82. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/mail.svg +0 -0
  83. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/mailmultiple.svg +0 -0
  84. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/mobiledevice.svg +0 -0
  85. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/office.svg +0 -0
  86. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/package-module.svg +0 -0
  87. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/paymentcard.svg +0 -0
  88. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/plane.svg +0 -0
  89. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/printer.svg +0 -0
  90. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/pyramid.svg +0 -0
  91. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/queue.svg +0 -0
  92. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/router.svg +0 -0
  93. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/server.svg +0 -0
  94. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/speech.svg +0 -0
  95. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/sphere.svg +0 -0
  96. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/storage.svg +0 -0
  97. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/switch-module.svg +0 -0
  98. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/tower.svg +0 -0
  99. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/truck-2.svg +0 -0
  100. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/truck.svg +0 -0
  101. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/user.svg +0 -0
  102. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/isometric/vm.svg +0 -0
  103. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/laptop.svg +0 -0
  104. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/router-network.svg +0 -0
  105. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/server-network.svg +0 -0
  106. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps}/assets/icons/server.svg +0 -0
  107. {unifi_network_maps-1.2.1/src/unifi_mermaid → unifi_network_maps-1.3.0/src/unifi_network_maps/io}/export.py +0 -0
  108. {unifi_network_maps-1.2.1 → unifi_network_maps-1.3.0}/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,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: unifi-network-maps
3
- Version: 1.2.1
4
- Summary: Dynamic UniFi -> Mermaid network maps
3
+ Version: 1.3.0
4
+ Summary: Dynamic UniFi -> network maps in mermaid or svg
5
5
  Author: Merlijn
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/merlijntishauser/unifi-network-maps
@@ -26,6 +26,7 @@ License-File: LICENSE
26
26
  License-File: LICENSES.md
27
27
  Requires-Dist: unifi-controller-api
28
28
  Requires-Dist: python-dotenv
29
+ Requires-Dist: PyYAML
29
30
  Provides-Extra: dev
30
31
  Requires-Dist: pre-commit; extra == "dev"
31
32
  Requires-Dist: pytest; extra == "dev"
@@ -66,6 +67,12 @@ export UNIFI_PASS=********
66
67
  export UNIFI_VERIFY_SSL=false
67
68
  ```
68
69
 
70
+ Use a custom env file:
71
+
72
+ ```bash
73
+ unifi-network-maps --env-file ./site.env --stdout
74
+ ```
75
+
69
76
  ## Usage
70
77
 
71
78
  Basic map (tree layout by LLDP hops):
@@ -137,24 +144,72 @@ See `LICENSES.md` for third-party license info.
137
144
 
138
145
  ## Options
139
146
 
140
- - `--format mermaid|svg|svg-iso`: output format (default mermaid).
147
+ The CLI groups options by category (`Source`, `Functional`, `Mermaid`, `SVG`, `Output`, `Debug`).
148
+
149
+ Source:
150
+ - `--site`: override `UNIFI_SITE`.
151
+ - `--env-file`: load environment variables from a specific `.env` file.
152
+
153
+ Functional:
141
154
  - `--include-ports`: show port labels (Mermaid shows both ends; SVG shows compact labels).
155
+ - `--include-clients`: add active wired clients as leaf nodes.
142
156
  - `--only-unifi`: only include neighbors that are UniFi devices.
157
+
158
+ Mermaid:
143
159
  - `--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
160
  - `--group-by-type`: group nodes by gateway/switch/AP in Mermaid subgraphs.
147
- - `--include-clients`: add active wired clients as leaf nodes.
148
161
  - `--legend-only`: render just the legend as a separate Mermaid graph (Mermaid only).
162
+
163
+ SVG:
164
+ - `--svg-width/--svg-height`: override SVG output dimensions.
165
+ - `--theme-file`: load a YAML theme for Mermaid + SVG colors (see `examples/theme.yaml` and `examples/theme-dark.yaml`).
166
+
167
+ Output:
168
+ - `--format mermaid|svg|svg-iso`: output format (default mermaid).
169
+ - `--stdout`: write output to stdout.
170
+ - `--markdown`: wrap Mermaid output in a code fence.
171
+
172
+ Debug:
149
173
  - `--debug-dump`: dump gateway + sample devices to stderr for debugging.
150
174
  - `--debug-sample N`: number of non-gateway devices in debug dump (default 2).
151
- - `--svg-width/--svg-height`: override SVG output dimensions.
152
175
 
153
176
  ## Notes
154
177
 
155
178
  - Default output is top-to-bottom (TB) and rendered as a hop-based tree from the gateway(s).
156
179
  - Nodes are color-coded by type (gateway/switch/AP/client) with a sensible default palette.
157
180
  - 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`.
181
+ - SVG output uses vendored device glyphs from `src/unifi_network_maps/assets/icons`.
159
182
  - Isometric SVG output uses MIT-licensed icons from `markmanx/isopacks`.
160
183
  - SVG port labels render inside child nodes for readability.
184
+
185
+ ## AI Disclosure
186
+
187
+ This project used OpenAI Codex as a coding assistant for portions of the implementation and documentation.
188
+
189
+ ## Theme file
190
+
191
+ Example theme YAML (override only the values you want):
192
+
193
+ ```yaml
194
+ mermaid:
195
+ nodes:
196
+ gateway:
197
+ fill: "#ffe3b3"
198
+ stroke: "#d98300"
199
+ poe_link: "#1e88e5"
200
+ svg:
201
+ links:
202
+ standard:
203
+ from: "#2ecc71"
204
+ to: "#1b8f4a"
205
+ poe:
206
+ from: "#1e88e5"
207
+ to: "#0d47a1"
208
+ nodes:
209
+ switch:
210
+ from: "#d6ecff"
211
+ to: "#b6dcff"
212
+ ```
213
+
214
+ The built-in themes live at `src/unifi_network_maps/assets/themes/default.yaml` and
215
+ `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):
@@ -102,24 +108,72 @@ See `LICENSES.md` for third-party license info.
102
108
 
103
109
  ## Options
104
110
 
105
- - `--format mermaid|svg|svg-iso`: output format (default mermaid).
111
+ The CLI groups options by category (`Source`, `Functional`, `Mermaid`, `SVG`, `Output`, `Debug`).
112
+
113
+ Source:
114
+ - `--site`: override `UNIFI_SITE`.
115
+ - `--env-file`: load environment variables from a specific `.env` file.
116
+
117
+ Functional:
106
118
  - `--include-ports`: show port labels (Mermaid shows both ends; SVG shows compact labels).
119
+ - `--include-clients`: add active wired clients as leaf nodes.
107
120
  - `--only-unifi`: only include neighbors that are UniFi devices.
121
+
122
+ Mermaid:
108
123
  - `--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
124
  - `--group-by-type`: group nodes by gateway/switch/AP in Mermaid subgraphs.
112
- - `--include-clients`: add active wired clients as leaf nodes.
113
125
  - `--legend-only`: render just the legend as a separate Mermaid graph (Mermaid only).
126
+
127
+ SVG:
128
+ - `--svg-width/--svg-height`: override SVG output dimensions.
129
+ - `--theme-file`: load a YAML theme for Mermaid + SVG colors (see `examples/theme.yaml` and `examples/theme-dark.yaml`).
130
+
131
+ Output:
132
+ - `--format mermaid|svg|svg-iso`: output format (default mermaid).
133
+ - `--stdout`: write output to stdout.
134
+ - `--markdown`: wrap Mermaid output in a code fence.
135
+
136
+ Debug:
114
137
  - `--debug-dump`: dump gateway + sample devices to stderr for debugging.
115
138
  - `--debug-sample N`: number of non-gateway devices in debug dump (default 2).
116
- - `--svg-width/--svg-height`: override SVG output dimensions.
117
139
 
118
140
  ## Notes
119
141
 
120
142
  - Default output is top-to-bottom (TB) and rendered as a hop-based tree from the gateway(s).
121
143
  - Nodes are color-coded by type (gateway/switch/AP/client) with a sensible default palette.
122
144
  - 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`.
145
+ - SVG output uses vendored device glyphs from `src/unifi_network_maps/assets/icons`.
124
146
  - Isometric SVG output uses MIT-licensed icons from `markmanx/isopacks`.
125
147
  - SVG port labels render inside child nodes for readability.
148
+
149
+ ## AI Disclosure
150
+
151
+ This project used OpenAI Codex as a coding assistant for portions of the implementation and documentation.
152
+
153
+ ## Theme file
154
+
155
+ Example theme YAML (override only the values you want):
156
+
157
+ ```yaml
158
+ mermaid:
159
+ nodes:
160
+ gateway:
161
+ fill: "#ffe3b3"
162
+ stroke: "#d98300"
163
+ poe_link: "#1e88e5"
164
+ svg:
165
+ links:
166
+ standard:
167
+ from: "#2ecc71"
168
+ to: "#1b8f4a"
169
+ poe:
170
+ from: "#1e88e5"
171
+ to: "#0d47a1"
172
+ nodes:
173
+ switch:
174
+ from: "#d6ecff"
175
+ to: "#b6dcff"
176
+ ```
177
+
178
+ The built-in themes live at `src/unifi_network_maps/assets/themes/default.yaml` and
179
+ `src/unifi_network_maps/assets/themes/dark.yaml`.
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "unifi-network-maps"
7
- version = "1.2.1"
8
- description = "Dynamic UniFi -> Mermaid network maps"
7
+ version = "1.3.0"
8
+ description = "Dynamic UniFi -> network maps in mermaid or svg"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
11
11
  license = { text = "MIT" }
@@ -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.0"
@@ -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())