Hi,
Thought I’d share my yaml tempalte to monitor HDD smart status.
Requirements
- smartmontools v7.0 or above (because v7 and above has json output).
- check your smartctl version by typing
smartctl --version
in terminal - you need to setup a cronjob to run the smartctl program to poll the HDD
- use the smartctl option
--nocheck standby
so it doesn’t wake up any HDD that are sleeping. - the yaml code reads a .json file generated by smartctl (smartmontools) and turns out into a template sensor.
Screenshot:
This assumes you use packages and you have to white-list the directory where you will save the json files.
# configuration.yaml
homeassistant:
packages: !include_dir_named packages
whitelist_external_dirs:
- /config/smartctl
The yaml expects the json files to be located in /config/smartctl so create this subdirectory off the home assistant config directory.
/config/smartctl
Create a script to run smartctl to get the smart data and use root crontab sudo crontab -e
to execute the script regularly (see below).
Change sd{a..m}
to suit the number of HDD you have eg. sd{a..c}
will scan /dev/sda + /dev/sdb + /dev/sdc
Change the target directory to save the json files inside the home assistant directory
for me I use docker so it’s mapped to /home/mike/.docker/config/homeassistant/smartctl/
The sensor in homeassistant looks for the files at /config/smartctl
#!/bin/bash
for arg in sd{a..m}; do /usr/sbin/smartctl --info --all --json --nocheck standby /dev/$arg > /home/mike/.docker/config/homeassistant/smartctl/$arg.json; done
Duplicate the below yaml for each HDD you want to monitor and use a find + replace to replace “sda” with “sdb” or whatever your HDD is.
homeassistant:
customize:
sensor.hdd_sda:
friendly_name: PARITY-10TB1 # <-- GIVE YOUR HDD A FRIENDLY NAME IF YOU WANT
icon: mdi:harddisk
#################################################
#################################################
#################################################
sensor:
- platform: mqtt
name: hdd_sda
state_topic: 'smartctl/sda/state'
json_attributes_topic: 'smartctl/sda/attributes'
#################################################################################################################################
# #
# #!/bin/bash #
# /usr/sbin/smartctl --info --all --json --nocheck standby /dev/sda > /home/mike/.docker/config/homeassistant/smartctl/sda.json #
# #
#################################################################################################################################
- platform: command_line
name: smartctl_sda_json
command: "/bin/cat /config/smartctl/sda.json" # <--- THIS READS THE .JSON TXT FILE
value_template: "{{ value_json.smartctl.exit_status }}"
json_attributes:
- smartctl
- device
- model_name
- user_capacity
- smart_status
- ata_smart_attributes
- temperature
- ata_smart_self_test_log
scan_interval: 30
automation:
- alias: "smartctl_sda"
trigger:
- platform: state
entity_id: sensor.smartctl_sda_json
- platform: homeassistant
event: start
action:
service_template: >-
{% if is_state('sensor.smartctl_sda_json','0') %}
script.smartctl_sda_awake
{% else %}
script.smartctl_sda_sleep
{% endif %}
script:
smartctl_sda_awake:
sequence:
- service: mqtt.publish
data:
topic: "smartctl/sda/state"
payload: "Awake"
retain: true
- service: mqtt.publish
data_template:
topic: "smartctl/sda/attributes"
# IF YOU HAVE PROBLEMS WITH THE SENSOR YOU CAN COPY+PASTE THE PAYLOAD INTO HOME ASSISTANT TEMPLATE EDITOR
payload: >-
{
"last updated": "{{ states('sensor.date_time') }}",
"model name": "{{ state_attr('sensor.smartctl_sda_json','model_name') | string }}",
"device": "{{ state_attr('sensor.smartctl_sda_json','device').name | string }}",
"size": "{{ (state_attr('sensor.smartctl_sda_json','user_capacity').bytes / 1000000000000) | round(2)}} TB",
"temperature": "{{ state_attr('sensor.smartctl_sda_json','temperature').current }}",
"smart status": "{% if states.sensor.smartctl_sda_json.attributes.smart_status.passed %} Healthy {% else %} Failed {% endif %}",
"power on time (hrs)": {% set ns = namespace(found=false) %}{% for i in state_attr('sensor.smartctl_sda_json','ata_smart_attributes').table %}{%- if i.id == 9 %}{% set ns.found = true %}"{{ i.raw.value }}"{% else %}{% endif -%}{% endfor %}{% if not ns.found %}"not available"{% endif %},
"power cycle count": {% set ns = namespace(found=false) %}{% for i in state_attr('sensor.smartctl_sda_json','ata_smart_attributes').table %}{%- if i.id == 12 %}{% set ns.found = true %}"{{ i.raw.value }}"{% else %}{% endif -%}{% endfor %}{% if not ns.found %}"not available"{% endif %},
"start stop count":{% set ns = namespace(found=false) %}{% for i in state_attr('sensor.smartctl_sda_json','ata_smart_attributes').table %}{%- if i.id == 4 %}{% set ns.found = true %}"{{ i.raw.value }}"{% else %}{% endif -%}{% endfor %}{% if not ns.found %}"not available"{% endif %},
"SMART5": {% set ns = namespace(found=false) %}{% for i in state_attr('sensor.smartctl_sda_json','ata_smart_attributes').table %}{%- if i.id == 5 %}{% set ns.found = true %}"{{ i.raw.value }}"{% else %}{% endif -%}{% endfor %}{% if not ns.found %}"not available"{% endif %},
"SMART187": {% set ns = namespace(found=false) %}{% for i in state_attr('sensor.smartctl_sda_json','ata_smart_attributes').table %}{%- if i.id == 187 %}{% set ns.found = true %}"{{ i.raw.value }}"{% else %}{% endif -%}{% endfor %}{% if not ns.found %}"not available"{% endif %},
"SMART188": {% set ns = namespace(found=false) %}{% for i in state_attr('sensor.smartctl_sda_json','ata_smart_attributes').table %}{%- if i.id == 188 %}{% set ns.found = true %}"{{ i.raw.value }}"{% else %}{% endif -%}{% endfor %}{% if not ns.found %}"not available"{% endif %},
"SMART197": {% set ns = namespace(found=false) %}{% for i in state_attr('sensor.smartctl_sda_json','ata_smart_attributes').table %}{%- if i.id == 197 %}{% set ns.found = true %}"{{ i.raw.value }}"{% else %}{% endif -%}{% endfor %}{% if not ns.found %}"not available"{% endif %},
"SMART198": {% set ns = namespace(found=false) %}{% for i in state_attr('sensor.smartctl_sda_json','ata_smart_attributes').table %}{%- if i.id == 198 %}{% set ns.found = true %}"{{ i.raw.value }}"{% else %}{% endif -%}{% endfor %}{% if not ns.found %}"not available"{% endif %},
{%- for i in state_attr('sensor.smartctl_sda_json','ata_smart_self_test_log') -%}
{%- if i == "standard" -%}
{%- for x in state_attr('sensor.smartctl_sda_json','ata_smart_self_test_log').standard.table %}
"TEST {{ loop.index }}": "{{ x.type.string }}, {{ x.status.string }} @ {{x.lifetime_hours }} hrs",
{%- endfor -%}
{%- endif -%}
{%- if i == "extended" -%}
{%- for x in state_attr('sensor.smartctl_sda_json','ata_smart_self_test_log').extended.table %}
"TEST {{ loop.index }}": "{{ x.type.string }}, {{ x.status.string }} @ {{x.lifetime_hours }} hrs",
{%- endfor -%}
{%- endif -%}
{%- endfor %}
"SMART Key": "5=Reallocated_Sector_Ct 187=Reported_Uncorrect 188=Command_Timeout 197=Current_Pending_Sector 198=Offline_Uncorrectable",
"SMART Ref": "https://www.backblaze.com/blog/what-smart-stats-indicate-hard-drive-failures/"
}
retain: true
smartctl_sda_sleep:
sequence:
- service: mqtt.publish
data:
topic: "smartctl/sda/state"
payload: "Sleep"
retain: true