Skip to content

Network Printers

Bubori Attila edited this page Aug 11, 2026 · 3 revisions

Network Printers

Network printers are tracked and queried via SNMP - this page covers how discovery, statistics, and the update schedule actually work under the hood.

Adding a printer

NetworkPrintersController::createNetworkPrinter() only requires a name and an IP address at creation time - it immediately calls snmpQueryPrinter() once to fill in everything else it can (brand, serial, MAC, toner levels) via SNMP.

snmpQueryPrinter() - the real data-gathering function

This is the function that actually populates printer data, using direct snmpget() calls (not a generic walk) against specific OIDs:

Data OID (or logic)
MAC address .1.3.6.1.2.1.2.2.1.6.1 (falls back to ...6.2 if empty)
Brand .1.3.6.1.2.1.25.3.2.1.3.1
Serial number .1.3.6.1.2.1.43.5.1.1.17.1 (Canon MF-series printers use a vendor-specific OID instead: .1.3.6.1.4.1.1602.1.2.1.4.0, matched by brand string)
Color capability .1.3.6.1.2.1.43.10.2.1.6.1.1

For color-capable printers, it also queries per-cartridge max/level OIDs (.1.3.6.1.2.1.43.11.1.1.8.x / .9.x) - and detects cartridge ordering automatically: it queries the first cartridge's description, and if it contains "black", assumes KCMY ordering (seen on some Epson ink printers); otherwise assumes standard CMYK ordering. This matters because different printer vendors number their color cartridges in different OID index orders - without this check, toner percentages would be attributed to the wrong color on some brands.

Existing values (brand, serial, MAC) are only re-queried if not already set (if (!isset($printer->brand))), so this is safe to call repeatedly without re-fetching static data every time.

snmpQueryPrinterSupplies() - dead code, not called anywhere

There is a second SNMP method, snmpQueryPrinterSupplies(), marked with a TODO comment and mostly commented-out logic (only the "supplies description" OID walk actually executes; the max-capacity and level OID walks are commented out, and nothing is ever saved to a model).

Update schedule

graph LR
    Cron["Laravel Scheduler<br/>dailyAt('10:00')"] --> Cmd["networkprinters:check<br/>(CheckNetworkPrinters command)"]
    Cmd --> Q["NetworkPrintersController::queryNetworkPrinters()"]
    Q -->|loops all printers| S["snmpQueryPrinter() per printer"]
    UI["'Update data' button<br/>(action: queryNetworkPrinters)"] --> Q
Loading

Automatic statistics collection runs once a day at 10:00 (routes/console.php: Schedule::command('networkprinters:check')->dailyAt('10:00')), backed by App\Console\Commands\CheckNetworkPrinters, which simply calls queryNetworkPrinters() - looping every registered printer through snmpQueryPrinter(). The same underlying function is also triggered on-demand by the "Update data" button in the UI (action: queryNetworkPrinters in the controller's payload() dispatcher), for an immediate refresh without waiting for the next scheduled run.

Reachability note: like all SNMP queries here, this only works for printers reachable from the server on port 161 with the correct read community (snmp-read-community in Global Settings, defaulting to public) - printers on a different subnet than the server, or with SNMP disabled/firewalled, will simply never update.

Deleting a printer

deleteNetworkPrinter() archives the printer's data as an HTML file (added to Documents), then deletes, in order: both directions of network_edges (source = "prID" and target = "prID"), NetworkPrinterStatistics, NetworkPrinterEvents, and finally the NetworkPrinters row itself. Unlike the original workstation-delete bug (see Known Limitations), this one already correctly handles both edge directions.

Clone this wiki locally