Skip to content

Commit

Permalink
add thermal zone metrics (#5)
Browse files Browse the repository at this point in the history
* add thermal zone metrics

- the mypy ignore for psutil.sensors_temperatures() is required as the subs do not provide this method but it is present at runtime

* fix mypy errors
  • Loading branch information
miaucl authored Sep 14, 2024
1 parent 91cc2c9 commit 482f4e0
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 4 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"jsons",
"levelname",
"markdownlint",
"miaucl",
"mkdocs",
"Mosquitto",
"mountpoint",
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ The sensor state equals average throughput of the interface during the collectio

This will publish network throughput information about Server1's `eth0` interface to the MQTT broker once every 60 seconds. The sensor state will equal the average network throughput over the previous 15 seconds.

### Thermal zones

`linux2mqtt` can publish temperature metrics for thermal zones using the `temp` option. Each thermal zone will present as a separate sensor in Home Assistant. The sensor state reports the temperature in `°C`. Additional data is accessible as state attributes on each sensor.

`linux2mqtt --name Server1 -vvvvv --cpu=60 --vm --temp`

## Compatibility

`linux2mqtt` has been tested to work on CentOS, Ubuntu, and Debian (Raspberry Pi), even tough some features are not available everywhere. **Python 3.10 (or above) is recommended.**
Expand Down
2 changes: 2 additions & 0 deletions linux2mqtt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
DiskUsageMetrics,
NetworkMetrics,
NetworkMetricThread,
TempMetrics,
VirtualMemoryMetrics,
)
from .type_definitions import (
Expand Down Expand Up @@ -79,6 +80,7 @@
"NetworkMetrics",
"NetworkMetricThread",
"DiskUsageMetrics",
"TempMetrics",
"HOMEASSISTANT_PREFIX_DEFAULT",
"MQTT_CLIENT_ID_DEFAULT",
"MQTT_PORT_DEFAULT",
Expand Down
12 changes: 12 additions & 0 deletions linux2mqtt/linux2mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from typing import Any, List

import paho.mqtt.client
import psutil

from . import __VERSION__
from .const import (
Expand All @@ -38,6 +39,7 @@
CPUMetrics,
DiskUsageMetrics,
NetworkMetrics,
TempMetrics,
VirtualMemoryMetrics,
)
from .type_definitions import Linux2MqttConfig, LinuxDeviceEntry
Expand Down Expand Up @@ -548,6 +550,9 @@ def main() -> None:
default=None,
metavar="NIC",
)
parser.add_argument(
"--temp", help="Publish temperature of thermal zones", action="store_true"
)

try:
args = parser.parse_args()
Expand Down Expand Up @@ -616,6 +621,13 @@ def main() -> None:
net = NetworkMetrics(n, i)
stats.add_metric(net)

if args.temp:
st = psutil.sensors_temperatures() # type: ignore
for device in st:
for thermal_zone in st[device]:
tm = TempMetrics(device=device, thermal_zone=thermal_zone.label)
stats.add_metric(tm)

if not (args.vm or args.cpu or args.du or args.net):
main_logger.warning("No metrics specified. Nothing will be published.")

Expand Down
78 changes: 77 additions & 1 deletion linux2mqtt/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class BaseMetric:

ha_sensor_type: SensorType = "sensor"

polled_result: Dict[str, str | int | float] | None
polled_result: Dict[str, str | int | float | None] | None

def __init__(self, *args: Any, **kwargs: Any) -> None:
"""Initialize base class."""
Expand Down Expand Up @@ -579,3 +579,79 @@ def poll(self, result_queue: Queue[BaseMetric]) -> bool:
th.daemon = True
th.start()
return True # Expect a deferred result


class TempMetrics(BaseMetric):
"""Thermal zones metric."""

icon = "mdi:thermometer"
device_class = "temperature"
unit_of_measurement = "°C"
state_field = "current"

_name_template = "Thermal Zone ({}/{})"
_device: str
_thermal_zone: str

def __init__(self, device: str, thermal_zone: str):
"""Initialize the thermal zone metric.
Parameters
----------
device
The device
thermal_zone
The thermal zone
Raises
------
Linux2MqttConfigException
Bad config
"""
super().__init__()
self._device = device
self._thermal_zone = thermal_zone
self._name = self._name_template.format(device, thermal_zone)

def poll(self, result_queue: Queue[Self]) -> bool:
"""Poll new data for the thermal zone metric.
Parameters
----------
result_queue
(Unused)
Returns
-------
bool
True as the data is readily available
Raises
------
Linux2MqttMetricsException
thermal zone information could not be gathered or prepared for publishing
"""
try:
st = psutil.sensors_temperatures() # type: ignore
thermal_zone = next(
(
item
for item in st.get(self._device, [])
if item.label == self._thermal_zone
),
None,
)
assert thermal_zone
self.polled_result = {
"label": thermal_zone.label,
"current": thermal_zone.current,
"high": thermal_zone.high,
"critical": thermal_zone.critical,
}
return False
except Exception as ex:
raise Linux2MqttMetricsException(
"Could not gather and publish thermal zone data"
) from ex
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
paho-mqtt
jsons
psutil
psutil>=5.0.0,<6.0.0
numpy
typing-extensions
4 changes: 2 additions & 2 deletions requirements_dev.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
paho-mqtt
types-paho-mqtt
jsons
psutil
types-psutil
psutil>=5.0.0,<6.0.0
types-psutil>=5.0.0,<6.0.0
numpy
typing-extensions
mypy>=1.8.0
Expand Down

0 comments on commit 482f4e0

Please sign in to comment.