Spark ⚡ - SNMP command to get data from APC UPS

I have an APC SRV2KA . It’s amazing, but I couldn’t get it to play nice with NUT . So I’m managing it with SNMPv3.

Setting up the credentials is straightforward with Powerchute Serial Shutdown . What was somewhat problematic was to figure out the Object Identifiers (OIDs) for specific values I needed to query from Home Assistant. Here are a few.

jorge@eternatus:~$  snmpwalk -v3 -u jorgeups -l authPriv -a SHA256 -A $APC_AUTH_PASS -x AES256 -X $APC_PRIVACY_PASS -n "" 10.20.101.17 1.3.6.1.4.1.318.1.1.1
iso.3.6.1.4.1.318.1.1.1.1.1.1.0 = STRING: "SRV 2K A"
iso.3.6.1.4.1.318.1.1.1.1.1.2.0 = STRING: "UPS_IDEN"
iso.3.6.1.4.1.318.1.1.1.1.2.1.0 = STRING: "436.13BT.D / 01.01a (1201 - 19)"
iso.3.6.1.4.1.318.1.1.1.1.2.2.0 = STRING: "11/10/23"
iso.3.6.1.4.1.318.1.1.1.1.2.3.0 = STRING: "9S2345A04593  "
iso.3.6.1.4.1.318.1.1.1.2.1.1.0 = INTEGER: 2
iso.3.6.1.4.1.318.1.1.1.2.1.2.0 = Timeticks: (0) 0:00:00.00
iso.3.6.1.4.1.318.1.1.1.2.1.3.0 = STRING: "Unavailable"
iso.3.6.1.4.1.318.1.1.1.2.2.1.0 = Gauge32: 50
iso.3.6.1.4.1.318.1.1.1.2.2.2.0 = Gauge32: 34
iso.3.6.1.4.1.318.1.1.1.2.2.3.0 = Timeticks: (1134000) 3:09:00.00
iso.3.6.1.4.1.318.1.1.1.2.2.4.0 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.2.2.5.0 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.2.2.8.0 = INTEGER: 50
iso.3.6.1.4.1.318.1.1.1.3.1.1.0 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.3.2.1.0 = Gauge32: 115
iso.3.6.1.4.1.318.1.1.1.3.2.4.0 = Gauge32: 59
iso.3.6.1.4.1.318.1.1.1.4.1.1.0 = INTEGER: 2
iso.3.6.1.4.1.318.1.1.1.4.1.2.0 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.4.2.1.0 = Gauge32: 115
iso.3.6.1.4.1.318.1.1.1.4.2.2.0 = Gauge32: 59
iso.3.6.1.4.1.318.1.1.1.4.2.3.0 = Gauge32: 0
iso.3.6.1.4.1.318.1.1.1.4.2.4.0 = Gauge32: 0
iso.3.6.1.4.1.318.1.1.1.5.2.1.0 = INTEGER: 115
iso.3.6.1.4.1.318.1.1.1.5.2.2.0 = STRING: "Unavailable"
iso.3.6.1.4.1.318.1.1.1.5.2.3.0 = STRING: "Unavailable"
iso.3.6.1.4.1.318.1.1.1.5.2.4.0 = INTEGER: 3
iso.3.6.1.4.1.318.1.1.1.5.2.7.0 = STRING: "Unavailable"
iso.3.6.1.4.1.318.1.1.1.5.2.8.0 = Timeticks: (60000) 0:10:00.00
iso.3.6.1.4.1.318.1.1.1.5.2.10.0 = Timeticks: (60000) 0:10:00.00
iso.3.6.1.4.1.318.1.1.1.5.2.16.1.1.1 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.5.2.16.1.1.2 = INTEGER: 2
iso.3.6.1.4.1.318.1.1.1.5.2.16.1.1.3 = INTEGER: 3
iso.3.6.1.4.1.318.1.1.1.5.2.16.1.1.4 = INTEGER: 4
iso.3.6.1.4.1.318.1.1.1.5.2.16.1.2.1 = OID: iso.3.6.1.4.1.318.1.1.1.5.2.1
iso.3.6.1.4.1.318.1.1.1.5.2.16.1.2.2 = OID: iso.3.6.1.4.1.318.1.1.1.5.2.2
iso.3.6.1.4.1.318.1.1.1.5.2.16.1.2.3 = OID: iso.3.6.1.4.1.318.1.1.1.5.2.3
iso.3.6.1.4.1.318.1.1.1.5.2.16.1.2.4 = OID: iso.3.6.1.4.1.318.1.1.1.5.2.5
iso.3.6.1.4.1.318.1.1.1.5.2.16.1.3.1 = STRING: "[120, 110, 115]"
iso.3.6.1.4.1.318.1.1.1.5.2.16.1.3.2 = STRING: "[]"
iso.3.6.1.4.1.318.1.1.1.5.2.16.1.3.3 = STRING: "[]"
iso.3.6.1.4.1.318.1.1.1.5.2.16.1.3.4 = STRING: "0 , 30 seconds"
iso.3.6.1.4.1.318.1.1.1.6.2.5.0 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.6.2.7.0 = INTEGER: 3
iso.3.6.1.4.1.318.1.1.1.7.2.1.0 = INTEGER: 2
iso.3.6.1.4.1.318.1.1.1.7.2.2.0 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.7.2.3.0 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.7.2.4.0 = STRING: "9/22/24"
iso.3.6.1.4.1.318.1.1.1.7.2.5.0 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.7.2.6.0 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.7.2.7.0 = STRING: "Unknown"
iso.3.6.1.4.1.318.1.1.1.8.1.0 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.12.1.1.0 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.12.1.2.1.1.1 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.12.1.2.1.2.1 = STRING: "Main Outlet Group"
iso.3.6.1.4.1.318.1.1.1.12.1.2.1.3.1 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.12.1.2.1.4.1 = INTEGER: 2
iso.3.6.1.4.1.318.1.1.1.12.1.2.1.5.1 = INTEGER: 2
iso.3.6.1.4.1.318.1.1.1.12.1.2.1.6.1 = STRING: "10000000000000000000000000000000"
iso.3.6.1.4.1.318.1.1.1.12.2.1.0 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.12.2.2.1.1.1 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.12.2.2.1.2.1 = STRING: "Main Outlet Group"
iso.3.6.1.4.1.318.1.1.1.12.2.2.1.3.1 = INTEGER: 0
iso.3.6.1.4.1.318.1.1.1.12.2.2.1.4.1 = INTEGER: 600
iso.3.6.1.4.1.318.1.1.1.12.2.2.1.5.1 = INTEGER: 4
iso.3.6.1.4.1.318.1.1.1.12.2.2.1.6.1 = INTEGER: 15
iso.3.6.1.4.1.318.1.1.1.12.2.2.1.7.1 = INTEGER: 2
iso.3.6.1.4.1.318.1.1.1.12.2.2.1.8.1 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.12.2.2.1.9.1 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.12.2.2.1.10.1 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.12.2.2.1.11.1 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.12.2.2.1.12.1 = INTEGER: 1
iso.3.6.1.4.1.318.1.1.1.12.2.2.1.13.1 = INTEGER: -1
iso.3.6.1.4.1.318.1.1.1.12.2.2.1.14.1 = INTEGER: -1

With that command I was able to get all the OIDs but figuring out what they meant required some research.

For instance, this value represents how much battery is left (as a percentage).

 jorge@eternatus:~$ snmpwalk -v3 -u jorgeups -l authPriv -a SHA256 -A $APC_AUTH_PASS -x AES256 -X $APC_PRIVACY_PASS -n "" 10.20.101.17 1.3.6.1.4.1.318.1.1.1.2.2.1.0
iso.3.6.1.4.1.318.1.1.1.2.2.1.0 = Gauge32: 51

Now that we’ve established how to get those values via the command line, here are some ready-to-use Home Assistant sensors. The following configuration can go in sensor.yml.

# This is the sensor demonstrated above, it shows the remaining
# battery as a percentage
- platform: snmp
  name: 'UPS Battery Capacity 2kva'
  host: 10.20.101.17
  baseoid: 1.3.6.1.4.1.318.1.1.1.2.2.1.0
  unit_of_measurement: '%'
  version: '3'
  username: jorgeups
  auth_key: !secret snmp_srv2_auth_key
  auth_protocol: hmac192-sha256
  priv_key: !secret snmp_srv2_priv_key
  priv_protocol: aes-cfb-256
# Returns the remaining runtime in seconds
- platform: snmp
  name: 'UPS Battery Runtime Remaining 2kva'
  host: 10.20.101.17
  baseoid: 1.3.6.1.4.1.318.1.1.1.2.2.3.0
  accept_errors: true
  unit_of_measurement: 's'
  version: '3'
  username: jorgeups
  auth_key: !secret snmp_srv2_auth_key
  auth_protocol: hmac192-sha256
  priv_key: !secret snmp_srv2_priv_key
  priv_protocol: aes-cfb-256
  value_template: "{{ (value | int / 100) | int }}"
# Returns the UPS model
- platform: snmp
  name: 'UPS Model 2kva'
  host: 10.20.101.17
  baseoid: 1.3.6.1.4.1.318.1.1.1.1.1.1.0
  version: '3'
  username: jorgeups
  auth_key: !secret snmp_srv2_auth_key
  auth_protocol: hmac192-sha256
  priv_key: !secret snmp_srv2_priv_key
  priv_protocol: aes-cfb-256
# Parses an integer that represents the UPS' current status
# and returns a descriptive string
- platform: snmp
  name: 'UPS Status 2kva'
  host: 10.20.101.17
  baseoid: 1.3.6.1.4.1.318.1.1.1.4.1.1.0 
  version: '3'
  username: jorgeups
  auth_key: !secret snmp_srv2_auth_key
  auth_protocol: hmac192-sha256
  priv_key: !secret snmp_srv2_priv_key
  priv_protocol: aes-cfb-256
  value_template: >
    {% set status = {
      1: 'unknown',
      2: 'onLine',
      3: 'onBattery',
      4: 'onSmartBoost',
      5: 'timedSleeping',
      6: 'softwareBypass',
      7: 'off',
      8: 'rebooting',
      9: 'switchedBypass',
      10: 'hardwareFailureBypass',
      11: 'sleepingUntilPowerReturn',
      12: 'onSmartTrim'
    } %}
    {{ status[value | int] if value | int in status else 'Invalid Status' }}    

This was all for today. Enjoy your UPS.

Buy Me a Coffee at ko-fi.com