The PSMQTT architecture can be described as:
flowchart TD
%% Nodes
OS([Linux/Windows/Mac OS HW interfaces])
SMART([Hard drive SMART data])
CLK((Clock))
MQTT([MQTT Broker])
psmqttTASK(PSMQTT task handler)
psmqttSCHED(PSMQTT scheduler)
psmqttFMT(PSMQTT formatter)
%% Edge connections between nodes
OS -->|psutil| psmqttTASK
SMART -->|pySMART| psmqttTASK
CLK --> psmqttSCHED
psmqttSCHED-->psmqttTASK
psmqttTASK-->psmqttFMT
psmqttFMT-->MQTT
%% Individual node styling.
style OS color:#FFFFFF, fill:#AA00FF, stroke:#AA00FF
style SMART color:#FFFFFF, stroke:#00C853, fill:#00C853
style CLK color:#FFFFFF, stroke:#2962FF, fill:#2962FF
style MQTT color:#FFFFFF, stroke:#2962FF, fill:#2962FF
The PSMQTT configuration file defines:
- periodicity of each PSMQTT action;
- which "sensor" has to be queried; PSMQTT uses psutil and pySMART libraries to sense data from the HW of the device where PSMQTT runs (CPU, memory, temperature and fan sensors, SMART harddrive data, proces information, etc);
- how each sensor data is formatted into text;
- to which MQTT broker all the outputs will be published.
The following section provides more details about the config file syntax.
The PSMQTT configuration file is a YAML file.
The PSMQTT configuration file should be located in the same
directory containing psmqtt.py
; alternatevely you can specify the location of the
config file using the PSMQTTCONFIG environment variable
(e.g. setting PSMQTTCONFIG=~/my-config-psmqtt.yaml).
Please check the comments in the default psmqtt.yaml as documentation for most of the entries. Typically you will need to edit are those associated with the MQTT broker:
mqtt:
broker:
host: <put here the IP address of your MQTT broker>
port: <port where your MQTT broker listens, typically 1883>
The rest of this document will focus on the format of each "scheduling expression", whose general format is:
schedule:
- cron: <human-friendly CRON expression>
tasks:
- task: <task name>
params: [ <param1>, <param2>, <param3>, ... ]
formatter: <formatting rule>
topic: <MQTT topic>
ha_discovery:
<HomeAssistant discovery options>
Each of the following section describes in details the YAML portions that define each "scheduling expression":
<human-friendly CRON expression>
: CRON expression<task name>
and<param1>
,<param2>
,<param3>
, ...: Tasks<formatting rule>
: Formatting<MQTT topic>
: MQTT Topic<HomeAssistant discovery options>
: HomeAssistant Discovery Messages
The <human-friendly CRON expression>
that appears in the scheduling expression
is a string encoding a recurrent rule,
like e.g. "every 5 minutes" or "every monday" or "every hour except 9pm, 10pm and 11pm".
You can check examples of recurring period definitions here.
Note that cron expressions should be unique; if there are several schedules with the same period only last one will be used.
PSMQTT supports a large number of "tasks". A "task" is the combination of
<task-name>
: the specification of which sensor should be read; this is just a string;- parameter list
<param1>
,<param2>
, ...,<paramN>
: these are either strings or integers represented as a YAML list (the preferred syntax is to use a comma-separated list enclosed by square brackets); such parameters act as additional selectors/filters for the sensor;
The meaning for <param1>
, <param2>
is task-dependent.
Also the number of required paraterms is task-dependent.
The result of each task are pushed to an MQTT topic. As an example:
schedule:
- cron: every 10sec
tasks:
- task: cpu_times_percent
params: [ system ]
configures PSMQTT to publish on the MQTT topic psmqtt/COMPUTER_NAME/cpu_times_percent/system
the value of the system
field returned by the psutil cpu_times_percent function.
Each task can be either a
- single-valued task: i.e., a task producing a single output value;
- multi-valued task: i.e., a task producing more than 1 output value; this is common when wildcard
*
parameters are used; in such case the MQTT topic associated with the task should actually be an MQTT topic prefix so that each task output will be published on a different topic. See also MQTT Topic for more information about MQTT topic configurations.
As an example:
schedule:
- cron: every 10sec
tasks:
- task: cpu_times_percent
params: [ "*" ]
topic: "cpu/*"
configures PSMQTT to publish every 10sec on several MQTT topics:
- psmqtt/COMPUTER_NAME/cpu/user the value of the
user
field returned by the psutil cpu_times_percent function. - psmqtt/COMPUTER_NAME/cpu/nice the value of the
nice
field returned by the psutil cpu_times_percent function. - psmqtt/COMPUTER_NAME/cpu/system the value of the
system
field returned by the psutil cpu_times_percent function.
... etc etc ...
Most tasks support also the join wildcard +
parameter to get all possible fields of the task output in one single topic, encoding them as a JSON string; in other words a single MQTT message will be published
on a single MQTT topic with a message payload containing a JSON string.
As an example:
schedule:
- cron: every 10sec
tasks:
- task: cpu_times_percent
params: [ "+" ]
topic: "cpu"
configures PSMQTT to publish on the MQTT topic psmqtt/COMPUTER_NAME/cpu
the JSON encoding of what is returned by the psutil cpu_times_percent function, e.g. {"user": 12.0, "nice": 1.0, "system": 5.0, ...}
.
In case of task execution error, the error message is sent to a topic named
psmqtt/COMPUTER_NAME/error/TASK. Please check some MQTT documentation to understand the role of the /
MQTT
topic level separator.
Here follows the reference documentation for all required tasks and their parameters:
- Task name:
cpu_percent
- Short description: CPU total usage in percentage. Full reference
- REQUIRED:
<param1>
: The wildcard*
or+
to select all the CPUs (multi-valued task) or the CPU index0
,1
,2
, etc to select a single CPU (single-valued task)
- Task name:
cpu_times
- Short description: CPU times information. Full reference
- REQUIRED:
<param1>
: The wildcard*
or+
to select all fields (multi-valued task) or a field name likeuser
,nice
,system
, etc (single-valued task).
- Task name:
cpu_times_percent
- Short description: CPU times in percentage. Full reference
- REQUIRED:
<param1>
: The wildcard*
or+
to select all fields (multi-valued task) or a field name likeuser
,nice
,system
, etc (single-valued task). Check full reference for all available fields - OPTIONAL:
<param2>
: The wildcard*
or+
to select all CPUs (multi-valued task) or the CPU index0
,1
,2
, etc to select a single CPU (single-valued task). Note that you cannot use a wildcard as<param2>
together with a wildcard on<param1>
.
- Task name:
cpu_stats
- Short description: CPU statistics. Full reference
- REQUIRED:
<param1>
: The wildcard*
or+
to select all fields (multi-valued task) or or a field name likectx_switches
,interrupts
,soft_interrupts
,syscalls
(single-valued task).
- Task name:
virtual_memory
- Short description: Virtual memory information. Full reference
- REQUIRED:
<param1>
: The wildcard*
or+
to select all fields (multi-valued task) or one oftotal
,available
,percent
, etc (single-valued task). Check full reference for all available fields
- Task name:
swap_memory
- Short description: Swap memory information. Full reference
- REQUIRED:
<param1>
: The wildcard*
or+
to select all fields (multi-valued task) or one oftotal
,used
,free
, etc (single-valued task). Check full reference for all available fields
- Task name:
disk_partitions
- Short description: List of mounted disk partitions. Full reference
- REQUIRED:
<param1>
: The wildcard*
or+
to select all fields (multi-valued task) or a field name likedevice
,mountpoint
,fstype
,opts
(single-valued task). - OPTIONAL:
<param2>
: The wildcard*
or+
to select all partitions (multi-valued task) or an index0
,1
,2
, etc to select a specific partition (single-valued task). Note that you cannot use a wildcard as<param2>
together with a wildcard on<param1>
.
- Task name:
disk_usage
- Short description: Disk usage for a particular drive. Full reference
- REQUIRED:
<param1>
: The wildcard*
or+
to select all fields (multi-valued task) or a field name liketotal
,used
,free
,percent
(single-valued task). - REQUIRED:
<param2>
: The path where disk usage must be measured, e.g./
,/var
or/home/<username>
.
- Task name:
disk_io_counters
- Short description: Disk I/O counters. Full reference
- REQUIRED:
<param1>
: The wildcard*
or+
to select all fields (multi-valued task) or a field name likeread_count
,write_count
,read_bytes
,write_bytes
,read_time
,write_time
, etc (single-valued task). Check full reference for all available fields - OPTIONAL:
<param2>
: The wildcard*
or+
to select all partitions/disks (multi-valued task) or the name of a specific drive e.g./dev/md0
or/dev/sda
to select just that partition/disk. If not provided, then the total disk I/O counters (e.g. total bytes read from all the partitions/disks) are produced in output, according to the field(s) selected with<param1>
. Note that you cannot use a wildcard as<param2>
together with a wildcard on<param1>
.
- Task name:
smart
- Short description: Self-Monitoring, Analysis and Reporting Technology System (SMART) counters built into most modern ATA/SATA, SCSI/SAS and NVMe disks. Full reference
- REQUIRED:
<param1>
: The name of a specific drive e.g./dev/md0
or/dev/sda
. - OPTIONAL:
<param2>
: The wildcard*
or+
to select all S.M.A.R.T. attributes (multi-valued task) or a field name likeinterface
,is_ssd
,model
,name
,path
,rotation_rate
,serial
,smart_capable
,smart_enabled
,smart_status
,temperature
,test_capabilities
(single-valued task). All SMART attributes are reported in fields namedattribute_raw[ATTRIBUTE_NAME]
. The availability of specific attributes depends on the disk vendor and disk model. E.g. a typical SMART attribute name would bePower_On_Hours
which can be selected using for<param2>
the valueattribute_raw[Power_On_Hours]
. All SMART tests (short self tests, long self tests, etc) are reported in fields namedtest[TEST_INDEX]
with<TEST_INDEX>
being a number0
,1
,2
, etc (depending on how many SMART tests were run on the disk). The value of eachtest[TEST_INDEX]
is a JSON string containing details about that test, e.g.hours
,type
,status
, etc. The tests are sorted byhours
in decreasing order so thattest[0]
always indicates the most recent SMART test results. You can try the following Python snippet on your prompt to see which SMART attributes are detected by pySMART library for e.g. your device/dev/sda
:sudo python3 -c 'import pySMART; pySMART.Device("/dev/sda").all_attributes()'
- Task name:
net_io_counters
- Short description: Network I/O counters. Full reference
- REQUIRED:
<param1>
: The wildcard*
or+
to select all fields (multi-valued task) or a field name likebytes_sent
,bytes_recv
,packets_sent
,packets_recv
, etc (single-valued task). Check full reference for all available fields - OPTIONAL:
<param2>
: The wildcard*
or+
to select all network interface cards (NICs) or a NIC name like e.g.eth0
,wlan0
,enp3s0f0
, etc to select a specific NIC (single-valued task). Note that you cannot use a wildcard as<param2>
together with a wildcard on<param1>
.
- Task name:
sensors_temperatures
- Short description: Hardware temperatures. Full reference
- REQUIRED:
<param1>
: The wildcard*
or+
to select all available sensor types (e.g.asus
,coretemp
,amdgpu
, etc; multi-valued task) or the name of a specific sensor type to select only that one (single-valued task). Try the following Python snippet on your prompt to see which temperature sensor types are detected by psutil library:python3 -c 'import psutil, pprint; pprint.pprint(psutil.sensors_temperatures())'
- OPTIONAL:
<param2>
: The wildcard*
or+
to select all temperature sensors of the selected sensor type (multi-valued task) or alabel
value to select a specific sensor (single-valued task). E.g. you might want to useCore 0
as label to publish only the temperature of the first logical core. - OPTIONAL:
<param3>
: The wildcard*
or+
to select all temperature information available from the selected sensors (multi-valued task) or field name likecurrent
,high
,critical
to select only a specific information (single-valued task).
- Task name:
sensors_fans
- Short description: Hardware fans speed. Full reference
- REQUIRED:
<param1>
: The wildcard*
or+
to select all available sensor types (e.g.asus
, etc) or the name of a specific sensor type to select only that one (single-valued task). Try the following Python snippet on your prompt to see which fan sensor types are detected by psutil library:python3 -c 'import psutil, pprint; pprint.pprint(psutil.sensors_fans())'
- OPTIONAL:
<param2>
: The wildcard*
or+
to select all fan sensors of the selected sensor type (multi-valued task) or alabel
value to select a specific sensor (single-valued task). E.g. you might want to usecpu_fan
as label to publish only the fan speed of the CPU. - OPTIONAL:
<param3>
: The wildcard*
or+
to select all information available from the selected sensors (multi-valued task) or field name likecurrent
to select only a specific information (single-valued task).
- Task name:
sensors_battery
- Short description: Battery status information. Full reference
- REQUIRED:
<param1>
: The wildcard*
or+
to select all fields (multi-valued task) or a field name likepercent
,secsleft
,power_plugged
, etc (single-valued task). Check full reference for all available fields and their meaning.
- Task name:
users
- Short description: Users currently connected on the system. Full reference
- REQUIRED:
<param1>
: The wildcard*
or+
to select all fields (multi-valued task) or a field name likename
,terminal
,host
,started
, etc (single-valued task). Check full reference for all available fields and their meaning. - OPTIONAL:
<param2>
: The wildcard*
or+
to select all users (multi-valued task) or an index0
,1
,2
, etc to select a specific user (single-valued task).
- Task name:
boot_time
- Short description: System boot time. Full reference
- NO PARAMETES
- Task name:
pids
- Short description: Currently running process IDs. Full reference
- REQUIRED:
<param1>
: The wildcard*
or+
to select all PIDs, thecount
string to return just the number of PIDs or an index0
,1
,2
, etc to select a specific process ID.
- Task name:
processes
- Short description: Single process parameters. Full reference
- REQUIRED:
<param1>
: one of- numeric ID of the process
top_cpu
- top CPU consuming processtop_cpu[N]
- CPU consuming process number Ntop_memory
- top memory consuming processtop_memory[N]
- memory consuming process number Npid[PATH]
- process with ID specified in the file having PATH path (.pid file).name[PATTERN]
- process with name matching PATTERN pattern (use*
to match zero or more characters,?
for single character)*
- to get value of some property for all processes. Topic per process ID+
- to get value of some property for all processes in one topic (JSON string)
- OPTIONAL:
<param2>
: one ofpid
- process IDppid -
parent process IDname
- process nameexe
- process executable filecwd
- process working directorycmdline/*
- command line. Topic per linecmdline/+
- command line in one topic (JSON string)cmdline/count
- number of command line linescmdline/{0/1/etc}
- command line single linestatus
- process status (running/sleeping/idle/dead/etc)username
- user started processcreate_time
- time when process was started (Unix timestamp)terminal
- terminal of the processuids/*
- process user IDs. Topic per parameteruids/+
- process user IDs in one topic (JSON string)uids/{real/effective/saved}
- process user IDs single parametergids/*
- process group IDs. Topic per parametergids/+
- process group IDs in one topic (JSON string)gids/{real/effective/saved}
- process group IDs single parametercpu_times/*
- process CPU times. Topic per parametercpu_times/+
- process CPU times in one topic (JSON string)cpu_times/{user/system/children_user/children_system}
- process CPU times single parametercpu_percent
- CPU percent used by processmemory_percent
- memory percent used by processmemory_info/*
- memory used by process. Topic per parametermemory_info/+
- memory used by process in one topic (JSON string)memory_info/{rss/vms/shared/text/lib/data/dirty/uss/pss/swap}
- memory used by process single parameterio_counters/*
- process I/O counters. Topic per parameterio_counters/+
- process I/O counters in one topic (JSON string)io_counters/{read_count/write_count/read_bytes/write_bytes}
- process I/O single counternum_threads
- number of threadsnum_fds
- number of file descriptorsnum_ctx_switches/*
- number of context switches. Topic per parameternum_ctx_switches/+
- number of context switches in one topic (JSON string)num_ctx_switches/{voluntary/involuntary}
- context switches single counternice
- nice value*
- all process properties. Topic per property+
- all process properties in one topic (JSON string)**
- all process properties and sub-properties. Topic per property**;
- all process properties and sub-properties in one topic (JSON string)
The output of each task can be formatted using
Jinja2 templates in the formatter
field of task definitions
E.g.:
schedule:
- cron: every 10sec
tasks:
- task: cpu_times_percent
params: [ "user" ]
formatter: "{{x}}%"
configures PSMQTT to append the %
symbol after CPU usage.
For multi-valued tasks (that use a wildcard *
) all outputs are
available:
- by name if they are named.
- as
x
if they are unnamed. - as
x[1]
,x[2]
, etc if they are numbered.
PSMQTT provides some Jinja2 filters:
KB
,MB
,GB
to format value in bytes as KBytes, MBytes or GBytes.uptime_str
to format Linux epochs (mostly the output of theboot_time
task) as a human friendly uptime string representation (e.g., the output string might look like "30 days, 5:18").uptime_sec
to format Linux epochs (mostly the output of theboot_time
task) as a number of seconds elapsed since last boot.iso8601_str
to format Linux epochs (mostly the output of theboot_time
task) as an ISO8601 timestamp; this is particularly useful to create HomeAssistant sensors with atimestamp
device class.
Examples:
- task: virtual_memory
params: [ "*" ]
# emit free virtual memory in %
formatter: "{{(100*free/total)|int}}%"
- task: virtual_memory
params: [ "free" ]
# emit free virtual memory in MB instead of bytes
formatter: "{{x|MB}}"
- task: cpu_times_percent
params: [ "user", "*" ]
# emit total CPU time spend in user mode for the first and second logical cores only
formatter: "{{x[0]+x[1]}}"
- task: boot_time
formatter: "{{x|uptime_str}}"
The <MQTT topic>
specification in each task definition is optional.
If it is not specified, PSMQTT will generate automatically an output MQTT topic
in the form psmqtt/COMPUTER_NAME/.
To customize the prefix psmqtt/COMPUTER_NAME you can use the mqtt.publish_topic_prefix
key in the configuraton file. E.g.:
mqtt:
publish_topic_prefix: my-prefix
configures PSMQTT to emit all outputs at my-prefix/.
It's important to note that when the task emits more than one output (multi-valued task) due to the use of the
wildcard *
character then the MQTT topic must be specified and must include the
wildcard *
character itself.
As an example the task
schedule:
- cron: every 10sec
tasks:
- task: cpu_times_percent
params: [ "*" ]
topic: "cpu/*"
is producing 10 outputs on a Linux system: one for each of the user
, nice
, system
,
idle
, iowait
, irq
, softirq
, steal
, guest
and guest_nice
fields emitted by psutil.
These 10 outputs must be published on 10 different MQTT topics.
The use of cpu/*
as MQTT topic configures PSMQTT to send the 10 outputs to the following 10 topics:
- psmqtt/COMPUTER_NAME/cpu/user
- psmqtt/COMPUTER_NAME/cpu/nice
- psmqtt/COMPUTER_NAME/cpu/system
- psmqtt/COMPUTER_NAME/cpu/idle
- psmqtt/COMPUTER_NAME/cpu/iowait
- psmqtt/COMPUTER_NAME/cpu/irq
- psmqtt/COMPUTER_NAME/cpu/softirq
- psmqtt/COMPUTER_NAME/cpu/steal
- psmqtt/COMPUTER_NAME/cpu/guest
- psmqtt/COMPUTER_NAME/cpu/guest_nice
If the wildcard *
character is used in the task parameters but the MQTT topic is not specified
or does not contain the wildcard *
character itself, then an error will be emitted (check psmqtt logs).
The <HomeAssistant discovery options>
specification in each task definition is optional.
If it is specified, PSMQTT will generate MQTT messages that follow the Home Assistant MQTT discovery message specs.
These messages are extremehely useful to quickly setup connect PSMQTT and Home Assistant (HA) together, since HA will automatically detect the presence of PSMQTT "sensors".
If you want to configure MQTT discovery messages for HA, you should:
- Ensure to enable the feature
mqtt:
ha_discovery:
enabled: true
- For each task specify as bare minimum the
ha_discovery.name
andha_discovery.platform
properties:
- task: cpu_percent
params: [ total ]
ha_discovery:
name: "CPU Percentage"
platform: sensor
Please note that PSMQTT will error-out if the ha_discovery
section is populated for a multi-valued
task.
Consider that the ha_discovery.name
will be the human-friendly name of the HA entity;
ha_discovery.platform
can be either sensor
or binary_sensor
.
Most of PSMQTT tasks produce sensor
s but there are a few exceptions, e.g. the power_plugged
field of
the sensors_battery
task (which is either "true" or "false") or the smart_status
field of the smart
task
(which is either "PASS" or "FAIL").
Additional HA discovery messages that you might want to set to improve the look&feel of the HA entities are:
ha_discovery:
name: <some friendly name>
platform: sensor|binary_sensor
device_class: temperature|duration|timestamp|problem|...
icon: mdi:<whatever>
unit_of_measurement: %|bytes|...
expire_after: <an integer number of seconds>
payload_on: <useful only for binary_sensor>
payload_off: <useful only for binary_sensor>
value_template: <tell HA how to render the number>
See MQTT Binary sensors and MQTT sensors docs by HomeAssistant for more details.
For the icon
field, you can use online resources for searching Material Design Icons.
Check also the default psmqtt.yaml for some examples or the PSMQTT configuration examples later in this document.
Note that PSMQTT will publish MQTT discovery messages in 2 cases:
- when an HomeAssistant restart is detected;
- at PSMQTT startup
This policy optimizes network traffic (reducing it to the minimal) but ensures that HomeAssistant
is always instantly updated on any PSMQTT sensor that is enriched with the ha_discovery
metadata.
The psmqtt.yaml file supports a configuration named "request_topic":
mqtt:
request_topic: request
This configuration allows you to specify an MQTT topic that will be subscribed by PSMQTT and used as input trigger for emitting measurements. This is an alternative way to use PSMQTT compared to the use of cron expressions.
E.g. to force PSMQTT to run the task:
- task: cpu_times_percent
params: [ "*" ]
topic: "cpu/*"
it's possible to send the YAML string above on the topic psmqtt/COMPUTER_NAME/request; the task will be executed immediately when received and will be interpreted like any other task in the configuration file.
PSMQTT provides some observability feature about itself in 2 forms:
- logs: each disconnection from MQTT broker, network issue or any failure in executing a configured task is obviously reported in the logs;
- in the psmqtt/COMPUTER_NAME/psmqtt_status topic, where 3 metrics are published:
num_tasks_errors
,num_tasks_success
andnum_mqtt_disconnects
; this feature is enabled by the configuration keyreport_status_period_sec
:
logging:
report_status_period_sec: 10
Of course another way to monitor whether PSMQTT is working correctly is to check whether the output MQTT topics are updated on the expected frequency.
If the HomeAssistant integration MQTT discovery messages are used, also note that PSMQTT will automatically configure
the expire_after
property of the sensors; that means that in case PSMQTT stops updating the sensor main topic for
a time longer than the expected frequency, then the sensor’s state becomes unavailable
. This offers another way
to monitor whether PSMQTT is working as intended from HomeAssistant.
Finally, PSMQTT is also configuring the MQTT Last Will message on the (fixed) topic psmqtt/COMPUTER_NAME/psmqtt_status.
Whenever PSMQTT goes online the payload online
is published on that topic, with a retained message.
Whenever PSMQTT goes offline the payload offline
is published on that topic, with a retained message.
This allows any other MQTT client to always immediately retrieve the actual status of a PSMQTT client: online/connected or offline/disconnected.
The following psmqtt.yaml
is an example intended to be used as reference for some
syntax rules explained in this document:
logging:
level: WARNING
report_status_period_sec: 10
mqtt:
broker:
host: 192.168.0.3
port: 1883
username: psmqtt
password: psmqtt-s3cr3t-pass
clientid: psmqtt
schedule:
- cron: "every 1 minute"
tasks:
- task: cpu_percent
params: [ total ]
ha_discovery:
name: "CPU Percentage"
platform: sensor
unit_of_measurement: "%"
icon: mdi:speedometer
- task: virtual_memory
params: [ percent ]
ha_discovery:
name: "Memory Percentage"
platform: sensor
unit_of_measurement: "%"
icon: mdi:memory
# cpu temp
- task: sensors_temperatures
params: [ rtk_thermal, 0 ]
ha_discovery:
name: "CPU Temperature"
platform: sensor
device_class: temperature
unit_of_measurement: "°C"
icon: mdi:thermometer
# temperatures for 2 HDD in RAID from S.M.A.R.T data
- task: smart
params: [ "/dev/sdc", temperature ]
ha_discovery:
name: "HDD1 Temperature"
platform: sensor
device_class: temperature
unit_of_measurement: "°C"
icon: mdi:thermometer
- task: smart
params: [ "/dev/sdd", temperature ]
ha_discovery:
name: "HDD2 Temperature"
platform: sensor
device_class: temperature
unit_of_measurement: "°C"
icon: mdi:thermometer
- cron: "every 1 hour"
tasks:
- task: disk_usage
params: [ percent, "/mnt/md0" ]
ha_discovery:
name: "RAID Array Disk Usage"
platform: sensor
unit_of_measurement: "%"
icon: mdi:harddisk
- cron: "every 3 hours"
tasks:
- task: boot_time
formatter: "{{x|iso8601_str}}"
ha_discovery:
name: "Uptime"
platform: sensor
device_class: timestamp
icon: mdi:calendar
value_template: "{{ as_datetime(value) }}"