From 4c461c14e18322991621527bf07b34690c83ba0d Mon Sep 17 00:00:00 2001 From: reachableceo Date: Thu, 3 Sep 2026 13:34:55 -0500 Subject: [PATCH] refactor: move HA tooling + reference packs to KNEL/pfv-bms [#762] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HomeAssistant/ is now a redirect stub; AGENTS.md layout updated. Zero HA impact — pfv-bms never loaded from PFVCluster. Detail: https://projects.knownelement.com/issues/762 --- AGENTS.md | 2 +- HomeAssistant/README.md | 42 +-- HomeAssistant/ha-ws-call.py | 53 ---- .../packs/automations-ups-alerts.yaml | 139 --------- HomeAssistant/packs/energy-plant-kwh.yaml | 62 ---- HomeAssistant/packs/sensors-snmp-plant.yaml | 292 ------------------ 6 files changed, 12 insertions(+), 578 deletions(-) delete mode 100644 HomeAssistant/ha-ws-call.py delete mode 100644 HomeAssistant/packs/automations-ups-alerts.yaml delete mode 100644 HomeAssistant/packs/energy-plant-kwh.yaml delete mode 100644 HomeAssistant/packs/sensors-snmp-plant.yaml diff --git a/AGENTS.md b/AGENTS.md index bf8269f..c1c7fdf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -355,7 +355,7 @@ Work tracking stays in [Redmine](https://projects.knownelement.com). ``` dcinfra/ Data-center infra: PDU (powerman), serial console (console), UPS (ups), sensors (temper) -HomeAssistant/ OAM: pfv-bms ops pointer + needfromcharles asks (live config SoR = KNEL/pfv-bms repo) +HomeAssistant/ Redirect stub — HA tooling + reference packs moved to KNEL/pfv-bms (tools/, docs/reference-packs/) [#762] netinfra/ DNS/NTP/DHCP setup + audit; DNS cluster replication (dns-cluster-setup); switch captures (switches); DHCP config (dhcp) k8s/ k3s cluster setup scripts (HA control plane over Tailscale) + docs/ diff --git a/HomeAssistant/README.md b/HomeAssistant/README.md index 4b8047b..edf6f5d 100644 --- a/HomeAssistant/README.md +++ b/HomeAssistant/README.md @@ -1,35 +1,15 @@ -# HomeAssistant/ — pfv-bms operational notes +# HomeAssistant/ — moved to KNEL/pfv-bms -**Config source of truth: [KNEL/pfv-bms](https://git.knownelement.com/KNEL/pfv-bms)** -(private). Everything live (YAML, dashboards, packages) is deployed by -pushing that repo — the `core_git_pull` add-on on pfv-bms polls every 300s, -pulls, and auto-restarts Home Assistant on config changes. +Everything Home-Assistant-related now lives in the config source of +truth: [KNEL/pfv-bms](https://git.knownelement.com/KNEL/pfv-bms) +(public, AGPLv3). -## Where things live - -| Thing | Location | +| Moved | New home | |---|---| -| HA configuration (live) | KNEL/pfv-bms repo → /config on pfv-bms (VM 100, pfv-tsys1, 4 vCPU / 6GB) | -| Deploy pipeline | core_git_pull add-on (deploy key `~/.creds/pfv-bms-gitpull`, read-only) | -| Host shell access | `VM_IP=pfv-bms-lan.knel.net VM_USER=root VM_PORT=22222 bash tests/remote.sh vm '...'` | -| HA REST API | `~/.creds/homeassistant.env` (token) | -| Global/Cloudron instance | https://building-management.knownelement.com (`~/.creds/cloudron-ha.env`) | -| Samba (interactive edits) | add-on; creds `~/.creds/pfv-bms-samba.env` | -| Custom components | on-box only, gitignored (HACS 2.0.5, Govee lasswellt v2026.8.7) | -| Reference packs (this dir) | `packs/` — see statuses below | +| `ha-ws-call.py` (websocket CLI) | `tools/ha-ws-call.py` | +| `packs/*.yaml` (reference packs) | `docs/reference-packs/` (reference only, not loaded) | -## packs/ status - -| File | Status | -|---|---| -| automations-ups-alerts.yaml | SUPERSEDED — live copy in KNEL/pfv-bms (retargeted to companion app) | -| sensors-snmp-plant.yaml | DEAD — legacy snmp sensor platform creates nothing in HA 2026.8; migration tracked in #618 | -| energy-plant-kwh.yaml | PENDING — Riemann-sum helper reference for the energy dashboard (#439) | - -## Related tickets - -#344 (umbrella) · #439 (UPS/alerts) · #614 (minisplit/BTU) · #618-#628 (roadmap) · #629 (Friday onsite) - -Knowledge docs live on -[Discourse VP TechOps](https://community.turnsys.com/c/vp-techops) — this -file is the repo-side operational pointer. +Operational facts (host access, REST API env, deploy pipeline) are +documented in the pfv-bms README and on +[Discourse VP TechOps](https://community.turnsys.com/c/vp-techops). +This stub remains for link compatibility. [#762] diff --git a/HomeAssistant/ha-ws-call.py b/HomeAssistant/ha-ws-call.py deleted file mode 100644 index 7836ae2..0000000 --- a/HomeAssistant/ha-ws-call.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python3 -"""ha-ws-call: send websocket commands to Home Assistant, print JSON replies. - -Env: HASS_URL (http(s)://host[:port]), HASS_TOKEN (long-lived token). -Args: one or more JSON command objects — argv literals or file paths. -Replies printed one-per-command, JSON indented. Stdlib + websockets only. -Usage example (docker, from repo root): - docker run --rm --network host --env-file ~/.creds/homeassistant.env \ - -v "$PWD/HomeAssistant:/w" python:3.12-alpine \ - sh -c 'pip install -q websockets && python /w/ha-ws-call.py "{...json...}"' -""" - -import asyncio -import json -import os -import sys - -try: - import websockets -except ImportError: - sys.exit("missing dependency: pip install websockets") - - -def load_cmd(arg): - if arg.startswith("{"): - return json.loads(arg) - with open(arg, encoding="latin1") as handle: - return json.load(handle) - - -async def main(): - base = os.environ["HASS_URL"] - url = base.replace("http", "ws", 1).rstrip("/") + "/api/websocket" - token = os.environ["HASS_TOKEN"] - cmds = [load_cmd(arg) for arg in sys.argv[1:]] - async with websockets.connect(url, max_size=16 * 1024 * 1024) as ws: - hello = json.loads(await ws.recv()) - if hello.get("type") != "auth_required": - sys.exit(f"unexpected hello: {hello}") - await ws.send(json.dumps({"type": "auth", "access_token": token})) - authed = json.loads(await ws.recv()) - if authed.get("type") != "auth_ok": - sys.exit(f"auth failed: {authed}") - for message_id, cmd in enumerate(cmds, start=1): - cmd = dict(cmd) - cmd["id"] = message_id - await ws.send(json.dumps(cmd)) - reply = json.loads(await ws.recv()) - print(json.dumps(reply, indent=1)) - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/HomeAssistant/packs/automations-ups-alerts.yaml b/HomeAssistant/packs/automations-ups-alerts.yaml deleted file mode 100644 index d9a0ed1..0000000 --- a/HomeAssistant/packs/automations-ups-alerts.yaml +++ /dev/null @@ -1,139 +0,0 @@ -# PFV UPS + plant alert automations for Home Assistant [#439] -# -# Paste into automations.yaml (or via UI: paste YAML directly into the -# automation editor). Delivery target: notify.pushover (add the Pushover -# integration first; interim targets that exist today: -# notify.mobile_app_ultix_sidecar / notify.mobile_app_ultix_mini / -# notify.mobile_app_allthes_ipad). -# -# ENTITY IDs: created by the NUT integration when you add the two UPS config -# entries (Settings > Devices & Services > Add Integration > Network UPS -# Tools; hosts pfv-tsys1.knel.net and pfv-tsys9.knel.net, port 3493, user -# homeassistant + the upsd.users password). Suggested device names: -# "tsys1 ups" and "tsys9 ups" -> entities below. If HA names them -# differently, check Developer Tools > States (search "_ups_status") and -# edit the entity_id lines to match. Nothing else needs changing. - -- alias: "PFV plant - UPS on battery" - id: pfv_plant_ups_on_battery - mode: single - triggers: - - trigger: state - entity_id: - - sensor.tsys1_ups_status - - sensor.tsys9_ups_status - conditions: - - condition: template - value_template: >- - {{ 'On Battery' in states(trigger.entity_id) }} - actions: - - action: notify.send_message - target: - entity_id: notify.pushover - data: - title: "POWER OUTAGE" - message: >- - {{ state_attr(trigger.entity_id, 'friendly_name') }} lost utility - power and is ON BATTERY at {{ states('sensor.' ~ trigger.entity_id.split('.')[1] | replace('_status', '_battery_charge')) }}% charge. - -- alias: "PFV plant - UPS battery low" - id: pfv_plant_ups_battery_low - mode: single - triggers: - - trigger: numeric_state - entity_id: - - sensor.tsys1_ups_battery_charge - - sensor.tsys9_ups_battery_charge - below: 40 - conditions: - - condition: template - value_template: >- - {{ 'On Battery' in states(trigger.entity_id | replace('_battery_charge', '_status')) }} - actions: - - action: notify.send_message - target: - entity_id: notify.pushover - data: - title: "UPS BATTERY LOW" - message: >- - {{ trigger.entity_id }} at {{ states(trigger.entity_id) }}% while on - battery. Start graceful shutdown of VMs before hypervisors (#455 ordering). - data: - priority: 1 - -- alias: "PFV plant - UPS communication lost" - id: pfv_plant_ups_comm_lost - mode: single - triggers: - - trigger: state - entity_id: - - sensor.tsys1_ups_status - - sensor.tsys9_ups_status - to: unavailable - for: "00:05:00" - actions: - - action: notify.send_message - target: - entity_id: notify.pushover - data: - title: "UPS COMMS LOST" - message: >- - {{ trigger.entity_id }} unreachable for 5 minutes (nut-server or - network path down; tsys1 also hosts pfv-bms itself). - data: - priority: 1 - -- alias: "PFV plant - utility power restored" - id: pfv_plant_ups_power_restored - mode: single - triggers: - - trigger: state - entity_id: - - sensor.tsys1_ups_status - - sensor.tsys9_ups_status - conditions: - - condition: template - value_template: >- - {{ trigger.from_state is not none and 'On Battery' in trigger.from_state.state - and 'On Battery' not in states(trigger.entity_id) }} - actions: - - action: notify.send_message - target: - entity_id: notify.pushover - data: - title: "Power restored" - message: >- - {{ state_attr(trigger.entity_id, 'friendly_name') }} is back ONLINE. - -- alias: "PFV plant - high temperature" - id: pfv_plant_high_temperature - mode: single - triggers: - - trigger: numeric_state - entity_id: - - sensor.pfv_artroom_temperature - - sensor.pfv_garage_temperature - - sensor.pfv_tsys1_rack_temperature - - sensor.pfv_tsys3_cpu_temperature - - sensor.pfv_tsys4_ambient_temperature - - sensor.pfv_tsys5_ambient_temperature - - sensor.pfv_tsys6_cpu_temperature - - sensor.pfv_tsys7_cpu_temperature - - sensor.pfv_tsys9_cpu_temperature - - sensor.pfv_jetson_temperature - - sensor.pfv_svrpi_temperature - - sensor.pfv_subopi3_temperature - - sensor.pfv_subopi_dev_3_temperature - - sensor.pfv_subopi_dev_4_temperature - above: 104 - actions: - - action: notify.send_message - target: - entity_id: notify.pushover - data: - title: "HIGH TEMPERATURE" - message: >- - {{ trigger.entity_id }} is {{ states(trigger.entity_id) }}°F - (threshold 104°F). Check cooling/airflow. - data: - priority: 1 diff --git a/HomeAssistant/packs/energy-plant-kwh.yaml b/HomeAssistant/packs/energy-plant-kwh.yaml deleted file mode 100644 index 7f66780..0000000 --- a/HomeAssistant/packs/energy-plant-kwh.yaml +++ /dev/null @@ -1,62 +0,0 @@ -# PFV plant energy helpers (kWh) for Home Assistant [#439] -# -# Paste into configuration.yaml. Riemann-sum integral: W -> kWh with the -# `integration` sensor platform (kept across restarts). Feeds the Energy -# dashboard (Settings > Dashboards > Energy > add grid/device consumption -# sources pointing at these kWh sensors). -# -# Node power comes from the ACPI power_meter read through the SNMP extend -# (see sensors-snmp-plant.yaml): sensor.pfv_tsys6_node_power / -# sensor.pfv_tsys7_node_power, in watts. - -sensor: - - platform: integration - source: sensor.pfv_tsys6_node_power - name: "PFV tsys6 node energy" - unique_id: pfv_tsys6_node_energy - unit_prefix: k - round: 2 - method: left - max_sub_interval: - minutes: 5 - - - platform: integration - source: sensor.pfv_tsys7_node_power - name: "PFV tsys7 node energy" - unique_id: pfv_tsys7_node_energy - unit_prefix: k - round: 2 - method: left - max_sub_interval: - minutes: 5 - -# --------------------------------------------------------------------------- -# UPS load -> energy (APC on tsys1, Tripp Lite on tsys9): -# Preferred source is the NUT diagnostic sensor "Real power (W)" — enable it -# on the NUT device page (diagnostics are disabled by default). If your UPS -# does not expose real power, uncomment the template-watts fallback below and -# fill in the nominal wattage from the UPS nameplate. -# -# - platform: integration -# source: sensor.tsys1_ups_watts -# name: "PFV tsys1 UPS energy" -# unique_id: pfv_tsys1_ups_energy -# unit_prefix: k -# round: 2 -# method: left -# max_sub_interval: -# minutes: 5 -# -# Fallback template (only if no realpower diagnostic entity exists): -# -# template: -# - sensor: -# - name: "PFV tsys1 UPS watts" -# unique_id: pfv_tsys1_ups_watts -# unit_of_measurement: "W" -# device_class: power -# state_class: measurement -# state: >- -# {{ (states('sensor.tsys1_ups_load') | float(0) -# * NOMINAL_WATTS / 100) | round(0) }} -# --------------------------------------------------------------------------- diff --git a/HomeAssistant/packs/sensors-snmp-plant.yaml b/HomeAssistant/packs/sensors-snmp-plant.yaml deleted file mode 100644 index 9fec4ae..0000000 --- a/HomeAssistant/packs/sensors-snmp-plant.yaml +++ /dev/null @@ -1,292 +0,0 @@ -# PFV physical-plant SNMP sensors for Home Assistant [#439] -# -# Paste the sensor block below into pfv-bms configuration.yaml (or an -# !include). All temperatures are converted C to F at the display layer per -# founder ruling 2026-08-27 (transport stays lm-sensors format, °C). -# -# Source: lmsensors-extend snmpd extend, deployed on all 7 Proxmox hosts + -# stlpc-artroom + stlpc-garage (see dcinfra/sensors/temper/). -# Extend OID: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 -# -# Hosts resolve via knel.net DNS from pfv-bms (verify in Developer Tools > -# States after reload; if a host shows 'unknown' check DNS + the snmpd -# source ACL which already includes the pfv-bms LAN IP 192.168.3.12). -# -# Per founder ruling (#343): LibreNMS does NOT graph temperatures; these HA -# sensors are the canonical environmental record for the plant. - -sensor: - # --- TEMPer USB probe hosts (External probe, Internal fallback) --- - - platform: snmp - name: "PFV artroom temperature" - host: stlpc-artroom.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: temperature - state_class: measurement - unit_of_measurement: "°F" - unique_id: pfv_artroom_temperature - value_template: >- - {% set ext = value | regex_findall('External:\s*\+?(-?\d+\.?\d*)') %} - {% set int = value | regex_findall('Internal:\s*\+?(-?\d+\.?\d*)') %} - {% set c = (ext | first) if ext else ((int | first) if int else none) %} - {{ ((c | float * 9 / 5) + 32) | round(1) if c is not none else 'unknown' }} - - - platform: snmp - name: "PFV garage temperature" - host: stlpc-garage.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: temperature - state_class: measurement - unit_of_measurement: "°F" - unique_id: pfv_garage_temperature - value_template: >- - {% set ext = value | regex_findall('External:\s*\+?(-?\d+\.?\d*)') %} - {% set int = value | regex_findall('Internal:\s*\+?(-?\d+\.?\d*)') %} - {% set c = (ext | first) if ext else ((int | first) if int else none) %} - {{ ((c | float * 9 / 5) + 32) | round(1) if c is not none else 'unknown' }} - - - platform: snmp - name: "PFV tsys1 rack temperature" - host: pfv-tsys1.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: temperature - state_class: measurement - unit_of_measurement: "°F" - unique_id: pfv_tsys1_rack_temperature - value_template: >- - {% set ext = value | regex_findall('External:\s*\+?(-?\d+\.?\d*)') %} - {% set int = value | regex_findall('Internal:\s*\+?(-?\d+\.?\d*)') %} - {% set c = (ext | first) if ext else ((int | first) if int else none) %} - {{ ((c | float * 9 / 5) + 32) | round(1) if c is not none else 'unknown' }} - - # --- Native lm-sensors hosts (label picked per host ground truth 2026-08-27) --- - # tsys3 Precision 7510: CPU package - - platform: snmp - name: "PFV tsys3 CPU temperature" - host: pfv-tsys3.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: temperature - state_class: measurement - unit_of_measurement: "°F" - unique_id: pfv_tsys3_cpu_temperature - value_template: >- - {% set m = value | regex_findall('Package id 0:\s*\+?(-?\d+\.?\d*)') %} - {{ ((m | first | float * 9 / 5) + 32) | round(1) if m else 'unknown' }} - - # tsys4 Precision T1700: Dell SMM ambient (board inlet) - - platform: snmp - name: "PFV tsys4 ambient temperature" - host: pfv-tsys4.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: temperature - state_class: measurement - unit_of_measurement: "°F" - unique_id: pfv_tsys4_ambient_temperature - value_template: >- - {% set m = value | regex_findall('Ambient:\s*\+?(-?\d+\.?\d*)') %} - {{ ((m | first | float * 9 / 5) + 32) | round(1) if m else 'unknown' }} - - # tsys5 Precision T7500: Dell SMM ambient (board inlet) - - platform: snmp - name: "PFV tsys5 ambient temperature" - host: pfv-tsys5.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: temperature - state_class: measurement - unit_of_measurement: "°F" - unique_id: pfv_tsys5_ambient_temperature - value_template: >- - {% set m = value | regex_findall('Ambient:\s*\+?(-?\d+\.?\d*)') %} - {{ ((m | first | float * 9 / 5) + 32) | round(1) if m else 'unknown' }} - - # tsys6 PowerEdge R610: socket-0 core temp (no Package label on Westmere) - - platform: snmp - name: "PFV tsys6 CPU temperature" - host: pfv-tsys6.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: temperature - state_class: measurement - unit_of_measurement: "°F" - unique_id: pfv_tsys6_cpu_temperature - value_template: >- - {% set m = value | regex_findall('Core 0:\s*\+?(-?\d+\.?\d*)') %} - {{ ((m | first | float * 9 / 5) + 32) | round(1) if m else 'unknown' }} - - # tsys6 ACPI power meter (node draw, watts) - - platform: snmp - name: "PFV tsys6 node power" - host: pfv-tsys6.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: power - state_class: measurement - unit_of_measurement: "W" - unique_id: pfv_tsys6_node_power - value_template: >- - {% set m = value | regex_findall('power1:\s*(\d+\.?\d*)\s*W') %} - {{ m | first | float if m else 'unknown' }} - - # tsys7 PowerEdge R620: package temp - - platform: snmp - name: "PFV tsys7 CPU temperature" - host: pfv-tsys7.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: temperature - state_class: measurement - unit_of_measurement: "°F" - unique_id: pfv_tsys7_cpu_temperature - value_template: >- - {% set m = value | regex_findall('Package id 0:\s*\+?(-?\d+\.?\d*)') %} - {{ ((m | first | float * 9 / 5) + 32) | round(1) if m else 'unknown' }} - - # tsys7 ACPI power meter (node draw, watts) - - platform: snmp - name: "PFV tsys7 node power" - host: pfv-tsys7.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: power - state_class: measurement - unit_of_measurement: "W" - unique_id: pfv_tsys7_node_power - value_template: >- - {% set m = value | regex_findall('power1:\s*(\d+\.?\d*)\s*W') %} - {{ m | first | float if m else 'unknown' }} - - # tsys9 OptiPlex 7080: package temp - - platform: snmp - name: "PFV tsys9 CPU temperature" - host: pfv-tsys9.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: temperature - state_class: measurement - unit_of_measurement: "°F" - unique_id: pfv_tsys9_cpu_temperature - value_template: >- - {% set m = value | regex_findall('Package id 0:\s*\+?(-?\d+\.?\d*)') %} - {{ ((m | first | float * 9 / 5) + 32) | round(1) if m else 'unknown' }} - - # --- SBC fleet (sysfs thermal fallback in lmsensors-extend v2; temp1 = zone0/SoC) --- - - platform: snmp - name: "PFV jetson temperature" - host: pfv-jetson-nano-1.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: temperature - state_class: measurement - unit_of_measurement: "°F" - unique_id: pfv_jetson_temperature - value_template: >- - {% set m = value | regex_findall('temp1:\s*\+?(-?\d+\.?\d*)') %} - {{ ((m | first | float * 9 / 5) + 32) | round(1) if m else 'unknown' }} - - - platform: snmp - name: "PFV svrpi temperature" - host: pfvsvrpi.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: temperature - state_class: measurement - unit_of_measurement: "°F" - unique_id: pfv_svrpi_temperature - value_template: >- - {% set m = value | regex_findall('temp1:\s*\+?(-?\d+\.?\d*)') %} - {{ ((m | first | float * 9 / 5) + 32) | round(1) if m else 'unknown' }} - - - platform: snmp - name: "PFV subopi3 temperature" - host: subopi3.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: temperature - state_class: measurement - unit_of_measurement: "°F" - unique_id: pfv_subopi3_temperature - value_template: >- - {% set m = value | regex_findall('temp1:\s*\+?(-?\d+\.?\d*)') %} - {{ ((m | first | float * 9 / 5) + 32) | round(1) if m else 'unknown' }} - - - platform: snmp - name: "PFV subopi-dev-3 temperature" - host: subopi-dev-3.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: temperature - state_class: measurement - unit_of_measurement: "°F" - unique_id: pfv_subopi_dev_3_temperature - value_template: >- - {% set m = value | regex_findall('temp1:\s*\+?(-?\d+\.?\d*)') %} - {{ ((m | first | float * 9 / 5) + 32) | round(1) if m else 'unknown' }} - - - platform: snmp - name: "PFV subopi-dev-4 temperature" - host: subopi-dev-4.knel.net - version: 2c - community: kn3lmgmt - baseoid: .1.3.6.1.4.1.8072.1.3.2.3.1.2.9.108.109.115.101.110.115.111.114.115 - accept_errors: true - device_class: temperature - state_class: measurement - unit_of_measurement: "°F" - unique_id: pfv_subopi_dev_4_temperature - value_template: >- - {% set m = value | regex_findall('temp1:\s*\+?(-?\d+\.?\d*)') %} - {{ ((m | first | float * 9 / 5) + 32) | round(1) if m else 'unknown' }} - -# --------------------------------------------------------------------------- -# PLACEHOLDERS — enable after dependencies land (do not invent OIDs live): -# -# Garage PDU (AP7830, SNMPv1, HA owns PDU power graphing per #343 ruling): -# Needs the custom v1 community from LibreNMS (founder: supply value as a -# HA secret) + OID discovery via snmpwalk of .1.3.6.1.4.1.318 subtree. -# - platform: snmp -# name: "PFV garage PDU current" -# host: -# version: 1 -# community: !secret pdu_community -# baseoid: -# -# iDRAC6 feeds (pfv-tsys6-oob / pfv-tsys7-oob, community kn3lmgmt) once the -# OOB ports are cabled (#460): inlet temp + system power via Dell PowerNet -# MIB. OIDs to be walked and pinned post-cabling. -# ---------------------------------------------------------------------------