You know what it’s like – so many Raspberry Pis at home… what started with a genuinely simple question: “how many Raspberry Pis on the home LAN are actually powered on right now?” grew into something much more. It should’ve been a one-liner….
It was not a one-liner. It’s never a one-liner.
Here’s roughly how it grew:
1๏ธโฃ pi_discover.py โ runs arp-scan (or falls back to nmap and a plain ping sweep, reading MACs back out of the kernel’s own ARP cache), then checks every MAC against the known Raspberry Pi Foundation / Trading Ltd OUI blocks. Point it at a subnet, get back exactly what’s actually a Pi. ๐ “Job’s a good ‘un“… Oh, wait….
2๏ธโฃ A persistent catalog โ just a CSV, keyed by MAC, tracking first-seen and last-seen. A Pi that’s powered off doesn’t disappear from the list anymore, it just shows up as offline ยท 3d ago.
3๏ธโฃ webapp.py โ because apparently typing a command in a terminal is just too much effort. A small Flask dashboard on top of the same CSV: a Rescan button, CSV/JSON export, a toggle between “Pi-only” and “show me the whole LAN.” How do you spell F-E-A-T-U-R-E C-R-E-E-P ???
4๏ธโฃ A full reskin โ lime-green top bar and all, reverse-engineered from a decade-old Hugo/Bootstrap theme I half-remembered lusting after on someone else’s site, tracked down via a Wayback Machine snapshot’s <head> tag because I couldn’t find the theme name “written down” anywhere…
5๏ธโฃ Hand-editable hardware fields โ type, RAM, disk, free text. OUI matching tells you that something’s a Pi, but not which Pi, and I got tired of guessing from memory ๐ฌ
6๏ธโฃ The first proper gotcha: a CM4 on a Waveshare dual-Ethernet base that refused to show up at all. Turns out the second RJ45 port isn’t CM4 silicon โ it’s a bolted-on Realtek PCIe chip with its own OUI, nothing to do with Raspberry Pi. A perfectly real Pi, invisible to a MAC-based scanner, because the interface it happened to be plugged into wasn’t Pi hardware. ๐
7๏ธโฃ A detour into whether any of this could run from my phone instead. Short answer: no. Android denies raw sockets and blocks reading the kernel’s ARP cache to every unrooted third-party app โ Termux, native NDK code, doesn’t matter which โ so you get a list of live IPs and zero MAC addresses. Apparently even the polished commercial scanner apps are mostly faking device identification via mDNS/UPnP chatter these days, not actual ARP, for the same reason.
8๏ธโฃ And finally (? really?), merge_catalogs.sh โ because a laptop and a Pi 5 scanning the same LAN from two different points see slightly different sets of devices, and by the time I’d hand-typed hardware info into one copy, a careless re-scan on the other could easily have blown it all away. Maybe.
Current tally: one shell script, one small web app, one merge tool, and a .gitignore that somehow took longer to get right than several of the actual features. No sign of this being finished.


One thought on “Pi Scanner: the shell script that turned into a web app”