Native lm-sensors output plus optional TEMPer USB probe, unified in
lm-sensors format behind one snmpd extend (lmsensors). Idempotent
deploy binds snmpd to explicit LAN+Tailscale addresses only and
source-scopes the community to the pollers (LibreNMS, Home Assistant
app-connector LAN IP, admin workstation, Cloudron) per the founder's
security ruling. TDD unit suite included; fleet verified live (6 hosts)
and negative-tested (refused source).
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
#!/bin/bash
|
||||
# lm-sensors extend for snmpd: native sensors + TEMPer USB block [#341/#439]
|
||||
#
|
||||
# Deployed to /usr/local/bin/lmsensors-extend on sensor hosts by deploy.sh.
|
||||
# Output = lm-sensors format, consumed by Home Assistant's SNMP integration
|
||||
# (nsExtendOutputFull."lmsensors") and, if enabled later, LibreNMS's
|
||||
# lm-sensors app.
|
||||
#
|
||||
# Layers (each optional, at least one required):
|
||||
# 1. native /usr/bin/sensors output (CPU/board temps, fans) — lm-sensors pkg
|
||||
# 2. TEMPer USB probe (temperusb in venv /opt/temper-venv) — probe-optional
|
||||
# (venv-on-host is founder-approved for sensor hosts, incl. Proxmox)
|
||||
set -euo pipefail
|
||||
|
||||
VENV_PY="${VENV_PY:-/opt/temper-venv/bin/python}"
|
||||
NATIVE_SENSORS_BIN="${NATIVE_SENSORS_BIN:-/usr/bin/sensors}"
|
||||
CHIP_NAME="${CHIP_NAME:-temper-usb-1}"
|
||||
|
||||
# Render lm-sensors format block from internal/external Celsius values.
|
||||
# Empty/absent external renders internal only. Non-numeric input is rejected.
|
||||
format_block() {
|
||||
local internal="${1:-}" external="${2:-}"
|
||||
local num_re='^-?[0-9]+(\.[0-9]+)?$'
|
||||
[[ "$internal" =~ $num_re ]] || {
|
||||
echo "error: internal temp not numeric: '$internal'" >&2
|
||||
return 1
|
||||
}
|
||||
local signed
|
||||
printf '%s\nAdapter: USB adapter\n' "$CHIP_NAME"
|
||||
signed="${internal#+}"; [[ "$signed" == -* ]] || signed="+$signed"
|
||||
printf 'Internal: %s°C\n' "$signed"
|
||||
if [[ -n "$external" && "$external" =~ $num_re ]]; then
|
||||
signed="${external#+}"; [[ "$signed" == -* ]] || signed="+$signed"
|
||||
printf 'External: %s°C\n' "$signed"
|
||||
fi
|
||||
}
|
||||
|
||||
# True when a TEMPer USB dongle (0c45:7401) is attached and the venv exists.
|
||||
has_temper_probe() {
|
||||
command -v lsusb >/dev/null 2>&1 || return 1
|
||||
[[ -x "$VENV_PY" ]] || return 1
|
||||
lsusb | grep -qi '0c45:7401'
|
||||
}
|
||||
|
||||
# Read the TEMPer probe via temperusb; prints "<internal> <external>" in C.
|
||||
# Sensor 0 = internal, sensor 1 = external probe (if attached).
|
||||
read_temper() {
|
||||
"$VENV_PY" - <<'PY'
|
||||
from temperusb import TemperHandler
|
||||
|
||||
internal = external = ""
|
||||
for device in TemperHandler().get_devices():
|
||||
try:
|
||||
temps = device.get_temperatures(sensors=[0, 1])
|
||||
except (ValueError, KeyError):
|
||||
temps = device.get_temperatures()
|
||||
for index, slot in ((0, "internal"), (1, "external")):
|
||||
reading = temps.get(index)
|
||||
if reading and reading.get("temperature_c") is not None:
|
||||
value = f"{reading['temperature_c']:.1f}"
|
||||
if slot == "internal":
|
||||
internal = value
|
||||
else:
|
||||
external = value
|
||||
print(f"{internal} {external}".strip())
|
||||
PY
|
||||
}
|
||||
|
||||
run_native_sensors() {
|
||||
[[ -x "$NATIVE_SENSORS_BIN" ]] || return 1
|
||||
"$NATIVE_SENSORS_BIN" 2>/dev/null
|
||||
}
|
||||
|
||||
main() {
|
||||
local out="" block internal external native
|
||||
if native="$(run_native_sensors)" && [[ -n "$native" ]]; then
|
||||
out+="$native"$'\n'
|
||||
fi
|
||||
if has_temper_probe; then
|
||||
if block="$(read_temper 2>/dev/null)" \
|
||||
&& read -r internal external <<<"$block" \
|
||||
&& block="$(format_block "${internal:-}" "${external:-}")"; then
|
||||
out+="$block"$'\n'
|
||||
else
|
||||
echo "warn: TEMPer probe present but read failed" >&2
|
||||
fi
|
||||
fi
|
||||
[[ -n "$out" ]] || {
|
||||
echo "error: no sensor sources available (lm-sensors pkg? TEMPer venv?)" >&2
|
||||
return 1
|
||||
}
|
||||
printf '%s' "$out"
|
||||
}
|
||||
|
||||
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
|
||||
main
|
||||
fi
|
||||
Reference in New Issue
Block a user