Commit Graph
9 Commits
Author SHA1 Message Date
jaredandClaude Opus 5.5 aa7341af06 Topology: a live page drawn from the real gear
Lint / JS (eslint) (push) Successful in 21s
Lint / Python (flake8) (push) Successful in 1m20s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Skipped
Security / Python Security (bandit) (push) Successful in 1m0s
Test / Python Tests (pytest) (push) Successful in 1m48s
Lint / Python (flake8) (pull_request) Successful in 1m44s
Lint / JS (eslint) (pull_request) Successful in 30s
Lint / Notify on failure (pull_request) Skipped
Lint / Deploy (pull_request) Skipped
Security / Python Security (bandit) (pull_request) Successful in 1m42s
Test / Python Tests (pytest) (pull_request) Successful in 1m16s
The dashboard's hand-drawn diagram was out of date. /topology replaces it
with the network as the switches report it, every device drawn to scale
from its faceplate or cutsheet front, and one cable per physical link
leaving the port it is plugged into.

- topology.py builds the graph: switch-to-switch cables seen from both ends
  are merged, servers get one cable per NIC, the gateway's internet port
  goes to the modem and on to the internet, unknown neighbours are stubs,
  and gear with no live cable is drawn where it was last seen.
- Ports named after a different device than the one plugged in are flagged.
- Cables show medium, speed, state and traffic; click one for its details,
  hover a device to trace its path to the internet; pan, zoom and filters.
- The monitor now keeps host_macs (MAC to host NIC) in link_stats.
- The old dashboard diagram and its JS and CSS are removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-14 19:30:59 -05:00
jaredandClaude Opus 5.5 d8e827c88b Rack: gear resting on other gear, and live desk switches on shelves
Lint / Python (flake8) (push) Failing after 47s
Lint / JS (eslint) (push) Successful in 17s
Lint / Deploy (push) Skipped
Security / Python Security (bandit) (push) Successful in 1m26s
Lint / Notify on failure (push) Successful in 7s
Test / Python Tests (pytest) (push) Successful in 2m2s
A USW Flex Mini lies on top of the NVR. A shelf item with Front drawing
"No shelf: gear resting on what is below" draws no tray or ears, so its
contents sit directly on the item under it.

UniFi desk switches on a shelf (Flex Mini, Flex) are drawn with their live
faceplate, scaled to their real width from Ubiquiti's tech specs (107 mm and
122.5 mm), with working ports. faceplateSvg() returns a faceplate's SVG on
its own so it can be placed inside the shelf drawing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 01:08:42 -05:00
jaredandClaude Opus 5.5 ce12dede5f Faceplates: USW Pro Max 24 PoE and 48 PoE
Lint / JS (eslint) (push) Successful in 12s
Lint / Python (flake8) (push) Successful in 1m10s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Skipped
Security / Python Security (bandit) (push) Successful in 1m11s
Test / Python Tests (pytest) (push) Successful in 1m42s
Lint / Python (flake8) (pull_request) Successful in 2m28s
Lint / JS (eslint) (pull_request) Successful in 14s
Lint / Notify on failure (pull_request) Skipped
Lint / Deploy (pull_request) Skipped
Security / Python Security (bandit) (pull_request) Successful in 1m10s
Test / Python Tests (pytest) (pull_request) Successful in 1m16s
Both laid out from the CC0 NetBox devicetype-library images, with jack
centres measured from them: the 24 has one row of 24 RJ45 in groups of 8
(17-24 at 2.5G) and 2 SFP+; the 48 has two rows, odd ports on top, in
groups of 16 (33-48 at 2.5G) and 4 SFP+ (49-52). The "2.5G" and "10G" bars
under the faster ports are drawn too (fpSpeedBar).

Registered as USPM24P/USPM48P with USPM24/USPM48 aliases, and as Front
drawing options so the new switch draws on the rack before it is adopted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 00:01:12 -05:00
jaredandClaude Opus 5.5 3c9e5fd593 Faceplates: model labels as printed on the units
Lint / JS (eslint) (push) Successful in 16s
Lint / Python (flake8) (push) Successful in 1m6s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Skipped
Lint / Python (flake8) (pull_request) Successful in 52s
Lint / JS (eslint) (pull_request) Successful in 7s
Lint / Notify on failure (pull_request) Skipped
Lint / Deploy (pull_request) Skipped
Security / Python Security (bandit) (pull_request) Successful in 53s
Security / Python Security (bandit) (push) Successful in 54s
Test / Python Tests (pytest) (push) Successful in 2m11s
Test / Python Tests (pytest) (pull_request) Successful in 2m16s
The label under each UniFi screen was one weight, left-aligned, and on the
UDM read "Dream Machine Pro". Checked against the NetBox reference photos
(and the UDM against the real unit), the labels are now centred under the
screen with the first word bold and the rest light: "UDM Pro",
"USW Pro" with its PoE mark, "USW", "NVR Pro", "USP PDU Pro". One helper
(fpModel) draws them all, so the NVR no longer looks bolder than the
switches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 23:36:23 -05:00
jaredandClaude Opus 5.5 565fdd81de Rack: NVR Pro as a real faceplate; Sliger and Rosewill touch-ups
Lint / JS (eslint) (push) Successful in 18s
Security / Python Security (bandit) (push) Successful in 1m45s
Lint / Python (flake8) (push) Successful in 1m25s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Skipped
Lint / Python (flake8) (pull_request) Successful in 52s
Lint / JS (eslint) (pull_request) Successful in 6s
Lint / Notify on failure (pull_request) Skipped
Lint / Deploy (pull_request) Skipped
Test / Python Tests (pytest) (push) Successful in 1m18s
Security / Python Security (bandit) (pull_request) Successful in 56s
Test / Python Tests (pytest) (pull_request) Successful in 53s
The hand-drawn NVR Pro didn't match the UniFi faceplates: flat colours,
low contrast and its own port shapes. It is now a FACEPLATES entry
(UNVRPRO) built from the same parts as the UDM Pro: metal body, RJ45 jack,
SFP+ cage, quad screen, vents and labels. Front drawing "UniFi NVR Pro"
uses it, and it would go live if UniFi ever reports the model.

Sliger bays are numbered 1-10 (driveAtlas's order); the Rosewill door is
perforated with a latch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 23:31:19 -05:00
jaredandClaude Opus 5.5 bdd68a397d Rack: link items to devices, shelves, several racks, export; fix layout and light mode
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (flake8) (push) Successful in 48s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Skipped
Security / Python Security (bandit) (push) Successful in 49s
Lint / Python (flake8) (pull_request) Successful in 51s
Test / Python Tests (pytest) (push) Successful in 1m2s
Lint / JS (eslint) (pull_request) Successful in 7s
Lint / Notify on failure (pull_request) Skipped
Lint / Deploy (pull_request) Skipped
Security / Python Security (bandit) (pull_request) Successful in 50s
Test / Python Tests (pytest) (pull_request) Successful in 53s
Cutsheet items gain a "Gandalf device" link, so an item named after the
product (UDM-Pro) shows the live device's faceplate, ports and status.
Cable checks, suggestions, tickets and the device page treat an item and
its linked device as one. Without this, product-named items drew as bare
name plates.

Items can sit on a shelf instead of a rack unit; the shelf draws what is
on it with live status. Items have a rack, the page shows a tab per rack
(config "racks"), and a rack can be downloaded as SVG or PNG.

The rack is centred, long runs of empty units fold into one band (with a
toggle), every device fills the 19" width, the UPS shows its front only,
and the rack keeps its own palette so it reads in light mode.

New cutsheet_items columns rack, shelf and device are added on first use.
Deleting a shelf, or making it something else, is refused while it holds
items; renaming it carries over.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 21:44:59 -05:00
jaredandClaude Opus 5.5 c262e5ecc8 Inventory links, cutsheet marks on faceplates, and single page titles
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (flake8) (push) Successful in 54s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Skipped
Security / Python Security (bandit) (push) Successful in 1m1s
Lint / JS (eslint) (pull_request) Successful in 19s
Test / Python Tests (pytest) (push) Successful in 2m6s
Security / Python Security (bandit) (pull_request) Successful in 1m18s
Lint / Python (flake8) (pull_request) Successful in 53s
Test / Python Tests (pytest) (pull_request) Successful in 1m1s
Lint / Notify on failure (pull_request) Skipped
Lint / Deploy (pull_request) Skipped
Device pages get an Inventory button: it opens the device's HomeBox record
once an admin pastes its URL (stored in the new device_links table; only
URLs on inventory.base_url are accepted), and searches the inventory for
the model until then. Tickets link the record too.

Faceplate ports with a documented cable get a corner dot: green matches,
red mismatch, grey documented but unconfirmed. The port's tooltip names
the cable, and a legend toggle (remembered per browser) hides them.

Page titles no longer repeat GANDALF ("Alert History - GANDALF - GANDALF").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 20:47:14 -05:00
jaredandClaude Opus 5.5 7e588e5b02 Keep every switch port and show SFP modules
Security / Python Security (bandit) (push) Successful in 1m50s
Test / Python Tests (pytest) (push) Successful in 1m52s
Lint / Python (flake8) (pull_request) Successful in 1m20s
Lint / Python (flake8) (push) Successful in 1m16s
Lint / JS (eslint) (pull_request) Successful in 10s
Lint / JS (eslint) (push) Successful in 15s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Skipped
Lint / Notify on failure (pull_request) Skipped
Lint / Deploy (pull_request) Skipped
Security / Python Security (bandit) (pull_request) Successful in 1m5s
Test / Python Tests (pytest) (pull_request) Successful in 1m7s
Ports were keyed by their UniFi name, so when two ports shared a name the
later one replaced the earlier. The 24-port switch lost port 13 this way
(ports 13 and 14 are both "Office TV"). A repeated name is now kept as
"<name> (Port N)".

Traffic rates are now matched to the previous poll by port number rather
than name. Names are re-read from UniFi every poll, so a port renamed
there keeps its rates instead of losing them for a cycle.

Collect what UniFi reports about each SFP cage: whether a module is
present, its type (DAC or optic), part, serial, fault flags, and DOM
readings when the module has them. The faceplate draws empty cages,
optics, DACs and unidentified modules differently and outlines a faulted
module in red. The port panel gets an SFP Module section. Both ends of a
DAC report the same cable serial, so each end links to the other.

Closes #7
Closes #8

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 14:37:08 -05:00
jaredandClaude Opus 5.5 051e70b82b Draw realistic front panels for every device model
Lint / JS (eslint) (push) Successful in 10s
Lint / Python (flake8) (push) Successful in 57s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Skipped
Security / Python Security (bandit) (push) Successful in 1m7s
Lint / Python (flake8) (pull_request) Successful in 59s
Test / Python Tests (pytest) (push) Successful in 1m22s
Lint / JS (eslint) (pull_request) Successful in 11s
Lint / Notify on failure (pull_request) Skipped
Lint / Deploy (pull_request) Skipped
Security / Python Security (bandit) (pull_request) Successful in 1m7s
Test / Python Tests (pytest) (pull_request) Successful in 1m28s
Replace the port blocks on device pages with SVG faceplates traced from
reference images: Dream Machine Pro, USW Pro 24 PoE, USW Aggregation,
USW Flex, USW Flex Mini, USP PDU Pro and UPS 2U Pro. Port LEDs use each
model's documented colors, and ports show a cable or module when up.

Remove SWITCH_LAYOUTS, which had wrong data: the aggregation switch was
numbered across the rows instead of odd over even, and the USW Flex had
an SFP cage it doesn't have. Models without a faceplate use plain blocks.

Show PDU and UPS outlets with on/off state and auto power-cycle, and let
the UPS page show its panel even though it reports no ports.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 11:11:48 -05:00