OpenWrt agent: add temperature sensors and harden wireless SNMP setup#613
OpenWrt agent: add temperature sensors and harden wireless SNMP setup#613perceival wants to merge 8 commits into
Conversation
|
@VVelox could you please take a look...? |
|
Updated the net-snmp OpenWrt integration: the distro extend now uses /etc/os-release for improved detection, and the unused snmpd-base-config file has been removed. |
|
Opened #618 to give this broader visibility and track the feature request separately from the implementation. The PR remains ready for review. |
|
@VVelox could you...? |
|
For what it's worth I'm testing this now and it's working well. |
|
Friendly bump @VVelox — @sshockley's report above ("testing this now and it's working well") confirms the agent works in a second OpenWrt environment beyond my own. PR is mergeable, no conflicts, CLA signed. Could you take a look when you have a minute? Happy to address any review feedback. |
laf
left a comment
There was a problem hiding this comment.
I honestly think this needs to be done using an LibreNMS MIB and snmpd pass_persist or possibly AgentX.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks for the review, @laf!
On MIB +
So: is |
Remove snmpd-config-generator.sh and setup-snmpd.sh (per review) and add snmp/Openwrt/README.md documenting the scripts plus the generator as an adaptable sample, including a safe re-apply using AUTOGEN markers.
|
I think it should be something like this: you can take a look at snmp/xcp-ng-vminfo it can be also good to look at mibs.observium.org if there is othere wireless metric to be included OPENWRT-MIB DEFINITIONS ::= BEGIN
IMPORTS
MODULE-IDENTITY, OBJECT-TYPE,
Integer32, Unsigned32, enterprises
FROM SNMPv2-SMI
DisplayString
FROM SNMPv2-TC
MODULE-COMPLIANCE, OBJECT-GROUP
FROM SNMPv2-CONF
InterfaceIndex
FROM IF-MIB;
openwrtMIB MODULE-IDENTITY
LAST-UPDATED "202606250000Z"
ORGANIZATION "Unassigned"
CONTACT-INFO
"OpenWrt SNMP agent MIB.
Enterprise OID: 1.3.6.1.4.1.60652.102.0 "
DESCRIPTION
"The OPENWRT-MIB describes OpenWrt wireless metrics exported by
the LibreNMS OpenWrt SNMP extension scripts."
REVISION "202606250000Z"
DESCRIPTION "Initial version for LibreNMS OpenWrt wireless extends."
::= { enterprises 60652 102 }
-- --------------------------------------------------------------------------
-- Top-level structure
-- --------------------------------------------------------------------------
openwrtObjects OBJECT IDENTIFIER ::= { openwrtMIB 1 }
openwrtConformance OBJECT IDENTIFIER ::= { openwrtMIB 2 }
openwrtCompliances OBJECT IDENTIFIER ::= { openwrtConformance 1 }
openwrtGroups OBJECT IDENTIFIER ::= { openwrtConformance 2 }
--- Maybe othere openwrt metadata
-- --------------------------------------------------------------------------
-- Section 10: Wireless metadata and aggregate scalars
-- --------------------------------------------------------------------------
openwrtWireless OBJECT IDENTIFIER ::= { openwrtObjects 10 }
openwrtWirelessInterfaceCount OBJECT-TYPE
SYNTAX Unsigned32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of active wireless interfaces"
::= { openwrtWireless 1 }
openwrtWirelessClientCount OBJECT-TYPE
SYNTAX Unsigned32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Aggregate count of unique associated wireless clients across the
exported interfaces.
NET-SNMP extend source: clients-wlan"
::= { openwrtWireless 2 }
-- --------------------------------------------------------------------------
-- Section 10B: Wireless interface table
-- --------------------------------------------------------------------------
openwrtWirelessInterfaceTable OBJECT-TYPE
SYNTAX SEQUENCE OF OpenwrtWirelessInterfaceEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"OpenWrt wireless interfaces and per-interface metrics."
::= { openwrtWireless 3 }
openwrtWirelessInterfaceEntry OBJECT-TYPE
SYNTAX OpenwrtWirelessInterfaceEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Metrics for one OpenWrt wireless interface. Rows are indexed by
the corresponding IF-MIB::ifIndex value."
INDEX { openwrtWlIfaceIfIndex }
::= { openwrtWirelessInterfaceTable 1 }
OpenwrtWirelessInterfaceEntry ::= SEQUENCE {
openwrtWlIfaceIfIndex InterfaceIndex,
openwrtWlIfaceName DisplayString,
openwrtWlIfaceLabel DisplayString,
openwrtWlIfaceClients Unsigned32,
openwrtWlIfaceFrequency Unsigned32,
openwrtWlIfaceNoiseFloor Integer32,
openwrtWlIfaceTxRateMin Unsigned32,
openwrtWlIfaceTxRateAvg Unsigned32,
openwrtWlIfaceTxRateMax Unsigned32,
openwrtWlIfaceRxRateMin Unsigned32,
openwrtWlIfaceRxRateAvg Unsigned32,
openwrtWlIfaceRxRateMax Unsigned32,
openwrtWlIfaceSnrMin Integer32,
openwrtWlIfaceSnrAvg Integer32,
openwrtWlIfaceSnrMax Integer32
}
openwrtWlIfaceIfIndex OBJECT-TYPE
SYNTAX InterfaceIndex
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Interface index from IF-MIB::ifIndex for this wireless interface."
::= { openwrtWirelessInterfaceEntry 1 }
openwrtWlIfaceName OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"OpenWrt wireless interface name, for example wlan0 or phy0-ap0."
::= { openwrtWirelessInterfaceEntry 2 }
openwrtWlIfaceLabel OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Display label for the wireless interface, normally the SSID. If
multiple interfaces share an SSID, wlInterfaces.sh appends a band
suffix such as 24, 5, or 6."
::= { openwrtWirelessInterfaceEntry 3 }
openwrtWlIfaceClients OBJECT-TYPE
SYNTAX Unsigned32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Associated client count for this wireless interface."
::= { openwrtWirelessInterfaceEntry 4 }
openwrtWlIfaceFrequency OBJECT-TYPE
SYNTAX Unsigned32
UNITS "MHz"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Current channel frequency in MHz. "
::= { openwrtWirelessInterfaceEntry 5 }
openwrtWlIfaceNoiseFloor OBJECT-TYPE
SYNTAX Integer32
UNITS "dBm"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Noise floor for this wireless interface in dBm. "
::= { openwrtWirelessInterfaceEntry 6 }
openwrtWlIfaceTxRateMin OBJECT-TYPE
SYNTAX Unsigned32
UNITS "Mbit/s"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Minimum transmit bitrate across associated stations."
::= { openwrtWirelessInterfaceEntry 7 }
openwrtWlIfaceTxRateAvg OBJECT-TYPE
SYNTAX Unsigned32
UNITS "Mbit/s"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Average transmit bitrate across associated stations. "
::= { openwrtWirelessInterfaceEntry 8 }
openwrtWlIfaceTxRateMax OBJECT-TYPE
SYNTAX Unsigned32
UNITS "Mbit/s"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Maximum transmit bitrate across associated stations. "
::= { openwrtWirelessInterfaceEntry 9 }
openwrtWlIfaceRxRateMin OBJECT-TYPE
SYNTAX Unsigned32
UNITS "Mbit/s"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Minimum receive bitrate across associated stations. "
::= { openwrtWirelessInterfaceEntry 10 }
openwrtWlIfaceRxRateAvg OBJECT-TYPE
SYNTAX Unsigned32
UNITS "Mbit/s"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Average receive bitrate across associated stations. "
::= { openwrtWirelessInterfaceEntry 11 }
openwrtWlIfaceRxRateMax OBJECT-TYPE
SYNTAX Unsigned32
UNITS "Mbit/s"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Maximum receive bitrate across associated stations. "
::= { openwrtWirelessInterfaceEntry 12 }
openwrtWlIfaceSnrMin OBJECT-TYPE
SYNTAX Integer32
UNITS "dB"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Minimum signal-to-noise ratio across associated stations. "
::= { openwrtWirelessInterfaceEntry 13 }
openwrtWlIfaceSnrAvg OBJECT-TYPE
SYNTAX Integer32
UNITS "dB"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Average signal-to-noise ratio across associated stations. "
::= { openwrtWirelessInterfaceEntry 14 }
openwrtWlIfaceSnrMax OBJECT-TYPE
SYNTAX Integer32
UNITS "dB"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Maximum signal-to-noise ratio across associated stations."
::= { openwrtWirelessInterfaceEntry 15 }
END |
|
Thanks @Torstein-Eide — this is exactly the steer I was hoping for, and the I pulled a clean baseline walk of vanilla OpenWrt (stock
One design point so the join is solid: the table index needs to be the device's real kernel @VVelox @laf — before I commit to the rework (it spans both this PR and server-side #19347), could you confirm the direction? Specifically:
Once the direction and the sub-arc are settled I'll do the OPENWRT-MIB + |
|
@perceival Yeah. Sounds good to me. Especially if it manages to avoid the mess of adding lots of stuff to the config, which is something I really hate about the current implementation for OpenWRT radio stuff... have to add a entry for every item instead one that will take care of it all. |
No the IfIndex is not unique across reboots, but other mibs uses it. There is logic in LibreNMS that groups sensors by IfIndex. |
|
Progress + a couple of things to ratify before I build the agent/server sides on top. I took @Torstein-Eide's draft and turned it into a lint-clean MIB. It's
One shape question before I wire it up: my baseline walk includes a client/STA-mode interface ( Temperature stays out of this MIB (rides LM-SENSORS-MIB emulation as before). Full MIB below for review: -- **********************************************************
-- OPENWRT-MIB
--
-- Custom MIB for OpenWrt wireless metrics exported by the
-- LibreNMS OpenWrt SNMP agent (pass_persist handler).
--
-- Enterprise Number: 60652 (LibreNMS, IANA PEN)
-- OID Base: .1.3.6.1.4.1.60652
--
-- NOTE: the sub-arc { LibreNMS 102 } is PROVISIONAL, following the
-- LibreNMS agent-MIB convention where OS/agent MIBs occupy the 100-block
-- (XCP-NG-VMINFO-MIB uses { LibreNMS 100 }; { LibreNMS 1 } is alerting).
-- Pending final assignment by a LibreNMS maintainer.
--
-- Temperature/thermal data is intentionally NOT defined here; it is
-- exported separately via LM-SENSORS-MIB emulation.
-- **********************************************************
OPENWRT-MIB DEFINITIONS ::= BEGIN
IMPORTS
MODULE-IDENTITY, OBJECT-TYPE,
Integer32, Unsigned32, enterprises
FROM SNMPv2-SMI
DisplayString
FROM SNMPv2-TC
MODULE-COMPLIANCE, OBJECT-GROUP
FROM SNMPv2-CONF
InterfaceIndex
FROM IF-MIB;
openwrtMIB MODULE-IDENTITY
LAST-UPDATED "202606250000Z"
ORGANIZATION "LibreNMS"
CONTACT-INFO
" LibreNMS Community
https://www.librenms.org
https://github.com/librenms/librenms
"
DESCRIPTION
"MIB module describing OpenWrt wireless metrics exported by the
LibreNMS OpenWrt SNMP agent. The agent discovers radios/VAPs live
(hostapd/iwinfo) at request time and serves this subtree from a
single net-snmp pass_persist handler, so no per-interface or
per-metric snmpd configuration is required."
REVISION "202606250000Z"
DESCRIPTION
"Initial version: wireless interface table and aggregate scalars."
::= { librenms 102 }
-- **********************************************************
-- Top-level enterprise OID
-- **********************************************************
-- Matches the `librenms' node descriptor used by LIBRENMS-NOTIFICATIONS-MIB
-- (lower-case per SMI naming rules; XCP-NG-VMINFO-MIB spells it `LibreNMS').
librenms OBJECT IDENTIFIER ::= { enterprises 60652 }
openwrtObjects OBJECT IDENTIFIER ::= { openwrtMIB 1 }
openwrtConformance OBJECT IDENTIFIER ::= { openwrtMIB 2 }
-- **********************************************************
-- Wireless objects
-- **********************************************************
openwrtWireless OBJECT IDENTIFIER ::= { openwrtObjects 10 }
openwrtWirelessInterfaceCount OBJECT-TYPE
SYNTAX Unsigned32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of active wireless interfaces exported in
openwrtWirelessInterfaceTable."
::= { openwrtWireless 1 }
openwrtWirelessClientCount OBJECT-TYPE
SYNTAX Unsigned32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Aggregate count of unique wireless clients served by this device
across its AP/master interfaces. MLO/MLD-related addresses are
de-duplicated so a single client associated over multiple links counts
once. Upstream associations on client/STA-mode interfaces are excluded
(this device's own uplink is not one of its clients)."
::= { openwrtWireless 2 }
-- **********************************************************
-- Wireless interface table
-- **********************************************************
openwrtWirelessInterfaceTable OBJECT-TYPE
SYNTAX SEQUENCE OF OpenwrtWirelessInterfaceEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"OpenWrt wireless interfaces and their per-interface metrics."
::= { openwrtWireless 3 }
openwrtWirelessInterfaceEntry OBJECT-TYPE
SYNTAX OpenwrtWirelessInterfaceEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Metrics for one OpenWrt wireless interface. Rows are indexed by the
corresponding IF-MIB ifIndex, so that this table joins directly onto
the standard interface table for the same VAP."
INDEX { openwrtWlIfaceIfIndex }
::= { openwrtWirelessInterfaceTable 1 }
OpenwrtWirelessInterfaceEntry ::= SEQUENCE {
openwrtWlIfaceIfIndex InterfaceIndex,
openwrtWlIfaceName DisplayString,
openwrtWlIfaceLabel DisplayString,
openwrtWlIfaceClients Unsigned32,
openwrtWlIfaceFrequency Unsigned32,
openwrtWlIfaceNoiseFloor Integer32,
openwrtWlIfaceTxRateMin Unsigned32,
openwrtWlIfaceTxRateAvg Unsigned32,
openwrtWlIfaceTxRateMax Unsigned32,
openwrtWlIfaceRxRateMin Unsigned32,
openwrtWlIfaceRxRateAvg Unsigned32,
openwrtWlIfaceRxRateMax Unsigned32,
openwrtWlIfaceSnrMin Integer32,
openwrtWlIfaceSnrAvg Integer32,
openwrtWlIfaceSnrMax Integer32
}
openwrtWlIfaceIfIndex OBJECT-TYPE
SYNTAX InterfaceIndex
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"The kernel interface index (IF-MIB ifIndex) of this wireless
interface, taken from /sys/class/net/<iface>/ifindex. Used as the
table index so rows align with the standard ifTable/ifXTable."
::= { openwrtWirelessInterfaceEntry 1 }
openwrtWlIfaceName OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"OpenWrt wireless interface name, for example wlan0 or phy0-ap0."
::= { openwrtWirelessInterfaceEntry 2 }
openwrtWlIfaceLabel OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Display label for the wireless interface, normally the SSID. If
multiple interfaces share an SSID, the agent appends a band suffix
such as 24, 5 or 6 to keep labels unique."
::= { openwrtWirelessInterfaceEntry 3 }
openwrtWlIfaceClients OBJECT-TYPE
SYNTAX Unsigned32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of stations associated with this wireless interface.
For an AP/master interface this is the count of connected clients.
For a client/STA-mode interface (e.g. a wireless uplink or backhaul)
this is the number of upstream associations, which is its peer count:
1 while associated to an AP, 0 when there is no peer (not associated /
link down) - so it doubles as a backhaul link-up indicator."
::= { openwrtWirelessInterfaceEntry 4 }
openwrtWlIfaceFrequency OBJECT-TYPE
SYNTAX Unsigned32
UNITS "MHz"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Current channel centre frequency in MHz."
::= { openwrtWirelessInterfaceEntry 5 }
openwrtWlIfaceNoiseFloor OBJECT-TYPE
SYNTAX Integer32
UNITS "dBm"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Noise floor for this wireless interface in dBm (typically negative)."
::= { openwrtWirelessInterfaceEntry 6 }
openwrtWlIfaceTxRateMin OBJECT-TYPE
SYNTAX Unsigned32
UNITS "Mbit/s"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Minimum transmit bitrate across associated stations, in Mbit/s.
Expressed in Mbit/s rather than bit/s so that Wi-Fi 6E/7 rates
(multi-Gbit/s) do not overflow Unsigned32."
::= { openwrtWirelessInterfaceEntry 7 }
openwrtWlIfaceTxRateAvg OBJECT-TYPE
SYNTAX Unsigned32
UNITS "Mbit/s"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Average transmit bitrate across associated stations, in Mbit/s."
::= { openwrtWirelessInterfaceEntry 8 }
openwrtWlIfaceTxRateMax OBJECT-TYPE
SYNTAX Unsigned32
UNITS "Mbit/s"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Maximum transmit bitrate across associated stations, in Mbit/s."
::= { openwrtWirelessInterfaceEntry 9 }
openwrtWlIfaceRxRateMin OBJECT-TYPE
SYNTAX Unsigned32
UNITS "Mbit/s"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Minimum receive bitrate across associated stations, in Mbit/s."
::= { openwrtWirelessInterfaceEntry 10 }
openwrtWlIfaceRxRateAvg OBJECT-TYPE
SYNTAX Unsigned32
UNITS "Mbit/s"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Average receive bitrate across associated stations, in Mbit/s."
::= { openwrtWirelessInterfaceEntry 11 }
openwrtWlIfaceRxRateMax OBJECT-TYPE
SYNTAX Unsigned32
UNITS "Mbit/s"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Maximum receive bitrate across associated stations, in Mbit/s."
::= { openwrtWirelessInterfaceEntry 12 }
openwrtWlIfaceSnrMin OBJECT-TYPE
SYNTAX Integer32
UNITS "dB"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Minimum signal-to-noise ratio across associated stations, in dB."
::= { openwrtWirelessInterfaceEntry 13 }
openwrtWlIfaceSnrAvg OBJECT-TYPE
SYNTAX Integer32
UNITS "dB"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Average signal-to-noise ratio across associated stations, in dB."
::= { openwrtWirelessInterfaceEntry 14 }
openwrtWlIfaceSnrMax OBJECT-TYPE
SYNTAX Integer32
UNITS "dB"
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Maximum signal-to-noise ratio across associated stations, in dB."
::= { openwrtWirelessInterfaceEntry 15 }
-- **********************************************************
-- Conformance
-- **********************************************************
openwrtCompliances OBJECT IDENTIFIER ::= { openwrtConformance 1 }
openwrtGroups OBJECT IDENTIFIER ::= { openwrtConformance 2 }
openwrtWirelessScalarGroup OBJECT-GROUP
OBJECTS {
openwrtWirelessInterfaceCount,
openwrtWirelessClientCount
}
STATUS current
DESCRIPTION
"Aggregate wireless scalars."
::= { openwrtGroups 1 }
openwrtWirelessInterfaceGroup OBJECT-GROUP
OBJECTS {
openwrtWlIfaceName,
openwrtWlIfaceLabel,
openwrtWlIfaceClients,
openwrtWlIfaceFrequency,
openwrtWlIfaceNoiseFloor,
openwrtWlIfaceTxRateMin,
openwrtWlIfaceTxRateAvg,
openwrtWlIfaceTxRateMax,
openwrtWlIfaceRxRateMin,
openwrtWlIfaceRxRateAvg,
openwrtWlIfaceRxRateMax,
openwrtWlIfaceSnrMin,
openwrtWlIfaceSnrAvg,
openwrtWlIfaceSnrMax
}
STATUS current
DESCRIPTION
"Per-interface wireless metrics."
::= { openwrtGroups 2 }
openwrtCompliance MODULE-COMPLIANCE
STATUS current
DESCRIPTION
"Compliance statement for OpenWrt wireless monitoring agents."
MODULE -- this module
MANDATORY-GROUPS {
openwrtWirelessScalarGroup,
openwrtWirelessInterfaceGroup
}
::= { openwrtCompliances 1 }
END |
|
Correction on my own STA-mode lean above — having thought about the device class, I'd now argue the opposite: include STA/client-mode interfaces in the table. On an OpenWrt AP/router a STA interface is almost always a wireless uplink/backhaul (mesh node, repeater, wireless WAN), and that's exactly the link where rate, SNR and noise floor are the most worth monitoring — arguably more than on a serving AP VAP. Practically it's just another wireless interface that needs watching. The only column that's vacuous for a STA is If it's useful to tell AP vs STA (vs mesh) apart on the LibreNMS side, one option is an optional |
For SNMP mib
and so on. |
|
ad. 1. Good point. Turning off lazy mode ;-)
Curious of your opinion. |
Serves the wireless subtree (.1.3.6.1.4.1.60652.102.1, OPENWRT-WIRELESS-MIB) from a single pass_persist registration instead of one extend per metric. Discovers radios/VAPs live via ubus (iwinfo/hostapd) with an iwinfo CLI fallback, and exposes a per-interface table indexed by ifIndex: clients, frequency, noise floor, tx/rx rate (min/avg/max), SNR, channel utilisation and tx power, plus aggregate scalars. Reuses wlInterfaces.sh and wlClients.sh for discovery and client counting; the snapshot is built once per request and cached so a walk does not re-run iwinfo per OID.
|
Yes a MIB (the files that defined what the OID means) can be split over multiple MIB files. A program will have if or case statements that gates what do to. The cost to read some more files and and format for SNMP is tiny for most low end devices, that OpenWrt runs on. LibreNMS will also reduse what is ask for from SNMP server, once a OID is add to a sensor it will only ask for that OID until next discovery. There is also no expatiation that you implement more that what is pressing for your need. Ie the common + wireless stuff. |
|
@Torstein-Eide Your is reasonable. Going with single program and multiple MIBs aproach. |
iwinfo's assoclist JSON has no per-station "snr" field, so the ubus path reported SNR 0 and an associated-station count of 0. Compute SNR per station as signal - noise (pairing the two arrays by index) and skip stations whose noise floor is unavailable (0); count associated stations from the signal array. Verified on hardware: a 2.4GHz VAP with 28 clients now reports SNR ~9..63 dB, while a 5GHz radio that does not expose survey noise reports 0.
Per review (single program, multiple MIBs): rename openwrt-wireless-pass.sh -> openwrt-snmp-pass.sh and register it once at the OpenWrt root (.1.3.6.1.4.1.60652.102) rather than just the wireless subtree. It now also serves the common metadata - openwrtMibVersion and openwrtOsVersion (from /etc/os-release) - alongside wireless; future areas add OIDs to the same OID-gated snapshot. Verified on OpenWrt (SNAPSHOT): metadata + wireless served, walk strictly ordered from the root.
This change is adding temperature sensors and improving (creating automation) in SNMP setup for WiFi sensors. Dependent on librenms/librenms#19347 (recreated after botched previous PR - #595).
Notes for reviewers:
wlInterfaces.sh
Replaces static interface mapping with live discovery from hostapd/iwinfo.
Filters inactive/placeholder VAPs and prefers active hostapd-managed interfaces.
Produces stable labels and handles duplicate SSIDs by appending band suffixes (24/5/6).
Keeps fallback logic for systems without full hostapd metadata.
wlClients.sh
Moves from simple station-dump counting to MAC-based counting with dedupe.
Supports both per-interface and aggregate modes.
Uses hostapd get_clients when available, with iwinfo fallback.
Deduplicates MLO/MLD-related addresses in aggregate mode to avoid overcounting.
wlRate.sh, wlNoiseFloor.sh, wlSNR.sh, wlFrequency.sh
Adds fallback parsing paths for client-mode interfaces where assoclist can be empty.
Normalizes output for SNMP extend compatibility (first line numeric value, optional second context line).
setup-snmpd.sh and snmpd-config-generator.sh
Introduces install/apply workflow for OpenWrt helper scripts.
Ensures managed LibreNMS blocks are replaced cleanly instead of duplicated.
Supports non-interactive apply (-y) and optional no-restart (--no-restart).
lm-sensors-pass.sh
Adds pass script implementing LM-SENSORS-MIB subtree behavior for thermal zones.
Handles both GET and GETNEXT traversal semantics for SNMP requests.
Scope check
PR remains constrained to OpenWrt integration paths with one upstream-based commit and the expected 12-file diff.
@VVelox I have recreated the PR from the scratch including your requested changes. Kindly please review.