mirror of
https://github.com/home-assistant/core.git
synced 2025-11-06 09:29:27 +00:00
snmp: Better sensor support to resolve previous issues (#113624)
Co-authored-by: Christian Kühnel <christian.kuehnel@gmail.com> Co-authored-by: jan iversen <jancasacondor@gmail.com>
This commit is contained in:
@@ -4,7 +4,9 @@ from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from struct import unpack
|
||||
|
||||
from pyasn1.codec.ber import decoder
|
||||
from pysnmp.error import PySnmpError
|
||||
import pysnmp.hlapi.asyncio as hlapi
|
||||
from pysnmp.hlapi.asyncio import (
|
||||
@@ -18,6 +20,8 @@ from pysnmp.hlapi.asyncio import (
|
||||
UsmUserData,
|
||||
getCmd,
|
||||
)
|
||||
from pysnmp.proto.rfc1902 import Opaque
|
||||
from pysnmp.proto.rfc1905 import NoSuchObject
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.sensor import CONF_STATE_CLASS, PLATFORM_SCHEMA
|
||||
@@ -165,7 +169,10 @@ async def async_setup_platform(
|
||||
errindication, _, _, _ = get_result
|
||||
|
||||
if errindication and not accept_errors:
|
||||
_LOGGER.error("Please check the details in the configuration file")
|
||||
_LOGGER.error(
|
||||
"Please check the details in the configuration file: %s",
|
||||
errindication,
|
||||
)
|
||||
return
|
||||
|
||||
name = config.get(CONF_NAME, Template(DEFAULT_NAME, hass))
|
||||
@@ -248,10 +255,44 @@ class SnmpData:
|
||||
_LOGGER.error(
|
||||
"SNMP error: %s at %s",
|
||||
errstatus.prettyPrint(),
|
||||
errindex and restable[-1][int(errindex) - 1] or "?",
|
||||
restable[-1][int(errindex) - 1] if errindex else "?",
|
||||
)
|
||||
elif (errindication or errstatus) and self._accept_errors:
|
||||
self.value = self._default_value
|
||||
else:
|
||||
for resrow in restable:
|
||||
self.value = resrow[-1].prettyPrint()
|
||||
self.value = self._decode_value(resrow[-1])
|
||||
|
||||
def _decode_value(self, value):
|
||||
"""Decode the different results we could get into strings."""
|
||||
|
||||
_LOGGER.debug(
|
||||
"SNMP OID %s received type=%s and data %s",
|
||||
self._baseoid,
|
||||
type(value),
|
||||
bytes(value),
|
||||
)
|
||||
if isinstance(value, NoSuchObject):
|
||||
_LOGGER.error(
|
||||
"SNMP error for OID %s: No Such Object currently exists at this OID",
|
||||
self._baseoid,
|
||||
)
|
||||
return self._default_value
|
||||
|
||||
if isinstance(value, Opaque):
|
||||
# Float data type is not supported by the pyasn1 library,
|
||||
# so we need to decode this type ourselves based on:
|
||||
# https://tools.ietf.org/html/draft-perkins-opaque-01
|
||||
if bytes(value).startswith(b"\x9f\x78"):
|
||||
return str(unpack("!f", bytes(value)[3:])[0])
|
||||
# Otherwise Opaque types should be asn1 encoded
|
||||
try:
|
||||
decoded_value, _ = decoder.decode(bytes(value))
|
||||
return str(decoded_value)
|
||||
# pylint: disable=broad-except
|
||||
except Exception as decode_exception:
|
||||
_LOGGER.error(
|
||||
"SNMP error in decoding opaque type: %s", decode_exception
|
||||
)
|
||||
return self._default_value
|
||||
return str(value)
|
||||
|
||||
Reference in New Issue
Block a user