1 """Support gathering system information of hosts which are running netdata."""
3 from __future__
import annotations
7 from netdata
import Netdata
8 from netdata.exceptions
import NetdataError
9 import voluptuous
as vol
12 PLATFORM_SCHEMA
as SENSOR_PLATFORM_SCHEMA,
30 _LOGGER = logging.getLogger(__name__)
32 CONF_DATA_GROUP =
"data_group"
33 CONF_ELEMENT =
"element"
34 CONF_INVERT =
"invert"
36 DEFAULT_HOST =
"localhost"
37 DEFAULT_NAME =
"Netdata"
40 DEFAULT_ICON =
"mdi:desktop-classic"
42 RESOURCE_SCHEMA = vol.Any(
44 vol.Required(CONF_DATA_GROUP): cv.string,
45 vol.Required(CONF_ELEMENT): cv.string,
46 vol.Optional(CONF_ICON, default=DEFAULT_ICON): cv.icon,
47 vol.Optional(CONF_INVERT, default=
False): cv.boolean,
51 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
53 vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string,
54 vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
55 vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
56 vol.Required(CONF_RESOURCES): vol.Schema({cv.string: RESOURCE_SCHEMA}),
64 async_add_entities: AddEntitiesCallback,
65 discovery_info: DiscoveryInfoType |
None =
None,
67 """Set up the Netdata sensor."""
69 name = config[CONF_NAME]
70 host = config[CONF_HOST]
71 port = config[CONF_PORT]
72 resources = config[CONF_RESOURCES]
77 await netdata.async_update()
79 if netdata.api.metrics
is None:
80 raise PlatformNotReady
82 dev: list[SensorEntity] = []
83 for entry, data
in resources.items():
84 icon = data[CONF_ICON]
85 sensor = data[CONF_DATA_GROUP]
86 element = data[CONF_ELEMENT]
87 invert = data[CONF_INVERT]
90 resource_data = netdata.api.metrics[sensor]
93 if resource_data[
"units"] ==
"percentage"
94 else resource_data[
"units"]
97 _LOGGER.error(
"Sensor is not available: %s", sensor)
102 netdata, name, sensor, sensor_name, element, icon, unit, invert
111 """Implementation of a Netdata sensor."""
113 def __init__(self, netdata, name, sensor, sensor_name, element, icon, unit, invert):
114 """Initialize the Netdata sensor."""
127 """Return the name of the sensor."""
128 return f
"{self._name} {self._sensor_name}"
132 """Return the unit the value is expressed in."""
137 """Return the icon to use in the frontend, if any."""
138 return self.
_icon_icon
142 """Return the state of the resources."""
147 """Could the resource be accessed during the last update call."""
148 return self.
netdatanetdata.available
151 """Get the latest data from Netdata REST API."""
153 resource_data = self.
netdatanetdata.api.metrics.get(self.
_sensor_sensor)
154 self.
_state_state = round(resource_data[
"dimensions"][self.
_element_element][
"value"], 2) * (
155 -1
if self.
_invert_invert
else 1
160 """Implementation of a Netdata alarm sensor."""
163 """Initialize the Netdata alarm sensor."""
172 """Return the name of the sensor."""
173 return f
"{self._name} Alarms"
177 """Return the state of the resources."""
182 """Status symbol if type is symbol."""
183 if self.
_state_state ==
"ok":
185 if self.
_state_state ==
"warning":
186 return "mdi:alert-outline"
187 if self.
_state_state ==
"critical":
189 return "mdi:crosshairs-question"
193 """Could the resource be accessed during the last update call."""
194 return self.
netdatanetdata.available
197 """Get the latest alarms from Netdata REST API."""
199 alarms = self.
netdatanetdata.api.alarms[
"alarms"]
201 number_of_alarms = len(alarms)
202 number_of_relevant_alarms = number_of_alarms
204 _LOGGER.debug(
"Host %s has %s alarms", self.
namenamename, number_of_alarms)
207 if alarms[alarm][
"recipient"] ==
"silent" or alarms[alarm][
"status"]
in (
212 number_of_relevant_alarms = number_of_relevant_alarms - 1
213 elif alarms[alarm][
"status"] ==
"CRITICAL":
214 self.
_state_state =
"critical"
216 self.
_state_state =
"ok" if number_of_relevant_alarms == 0
else "warning"
220 """The class for handling the data retrieval."""
223 """Initialize the data object."""
228 """Get the latest data from the Netdata REST API."""
231 await self.
apiapi.get_allmetrics()
232 await self.
apiapi.get_alarms()
235 _LOGGER.error(
"Unable to retrieve data from Netdata")
def __init__(self, netdata, name, host, port)
def native_unit_of_measurement(self)
def __init__(self, netdata, name, sensor, sensor_name, element, icon, unit, invert)
str|UndefinedType|None name(self)
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback async_add_entities, DiscoveryInfoType|None discovery_info=None)
httpx.AsyncClient get_async_client(HomeAssistant hass, bool verify_ssl=True)