Western Digital My Cloud

Looking to see if the Western Diginal MYCloud connect would be possible. Specifically I have a Western Digital NAS drive and would like to integrate it to HA so I can see important alarms.

Disk Space
Power Loss
Hardware Problems.
Network Activity

The Api documentation is here:

http://developer.mycloud.com/MCAPIindex.html

that will be great, hope someone look to it

Actually I don’t know if both of you read it but it’s actually talking about file transfert (what WD cloud is for!) and not device status.

But I agree, I would like to have my WD EX4100 status on my HA dashboard!

2 Likes

That Will be good o have 3tb my cloud

yes, that will be amazing!

One way to get info from the device is by using ssh.

So on the Home Assistant machine, first make ssh keys. Then appropriately locate and permission these files, and make a back up of them.

Next enable ssh on the WD Dashboard (RTFM > Configuring Settings > Network :grin:).

Log in to the WD as the ssh user and create a .ssh directory, permissioned as 700. Within that create a file named ‘authorized_keys’, permissioned as 600, and copy/paste the public key part of the ssh files pair, into here.

Next back up the .ssh directory:

tar -cvzf /shares/<username>/ssh_backup.tar.gz .ssh

Every time the WD reboots, it wipes the directory, so you’ll need to manually ssh in and restore the ssh directory:

tar -xvzf /shares/<username>/ssh_backup.tar.gz

Not ideal, but then it isn’t often that it needs a reboot.

With that done, back up the tar.gz file, to somewhere off the device.

Next test connecting using the keys, over ssh:

ssh -i <path_to_private_key_file> <ssh_user>@<device_ip_or_hostname>

… and accept when the confirmation happens.

Once the ssh part is working, the next task is to get the data. Here’s what I have in my sensors.yaml file:

- platform: command_line
  name: nas_cpu_temp
  unit_of_measurement: '°C'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> fan_control -g 0 | grep CPU | cut -d' ' -f 2 | cut -d'=' -f 2
# NAS Board Temperature
- platform: command_line
  name: nas_board_temp
  unit_of_measurement: '°C'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> fan_control -g 0 | grep Current | cut -d' ' -f 4
# NAS HD0 Temperature
- platform: command_line
  name: nas_hd0_temp
  unit_of_measurement: '°C'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> fan_control -g 0 | grep hd0 | cut -d' ' -f 2 | cut -d'=' -f 2
# NAS HD1 Temperature
- platform: command_line
  name: nas_hd1_temp
  unit_of_measurement: '°C'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> fan_control -g 0 | grep hd1 | cut -d' ' -f 2 | cut -d'=' -f 2
# NAS HD2 Temperature
- platform: command_line
  name: nas_hd2_temp
  unit_of_measurement: '°C'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> fan_control -g 0 | grep hd2 | cut -d' ' -f 2 | cut -d'=' -f 2
# NAS HD3 Temperature
- platform: command_line
  name: nas_hd3_temp
  unit_of_measurement: '°C'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> fan_control -g 0 | grep hd3 | cut -d' ' -f 2 | cut -d'=' -f 2
# NAS Fan RPM
- platform: command_line
  name: nas_fan_rpm
  unit_of_measurement: 'rpm'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> fan_control -g 4 | cut -d' ' -f 4
# NAS SMART Status
- platform: command_line
  name: nas_smart_status
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> /usr/local/sbin/getSmartStatus.sh
# NAS Firmware Status
- platform: command_line
  name: nas_firmware_status
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> /usr/local/sbin/getNewFirmwareAvailable.sh | sed 's/"//g' | sed 's/no upgrade/current/g'
# NAS Disk Space Total
- platform: command_line
  name: nas_disk_space_total
  unit_of_measurement: 'kB'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> df | sed -n '/HD_a2/s/ \+/ /gp' | cut -d' ' -f 2
# NAS Disk Space Used
- platform: command_line
  name: nas_disk_space_used
  unit_of_measurement: 'kB'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> df | sed -n '/HD_a2/s/ \+/ /gp' | cut -d' ' -f 3
# NAS Disk Space Free
- platform: command_line
  name: nas_disk_space_free
  unit_of_measurement: 'kB'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> df | sed -n '/HD_a2/s/ \+/ /gp' | cut -d' ' -f 4
# NAS Disk Space Percent Used
- platform: command_line
  name: nas_disk_perc_used
  unit_of_measurement: '%'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> df | sed -n '/HD_a2/s/ \+/ /gp' | cut -d' ' -f 5 | sed 's/%//g'
# NAS CPU Usage
- platform: command_line
  name: nas_cpu_idle
  unit_of_measurement: '%'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> mpstat | sed -n '/all/s/ \+/ /gp' | cut -d' ' -f 12 | sed 's/%//g'
# NAS RAM Total
- platform: command_line
  name: nas_mem_tot
  unit_of_measurement: 'kB'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> free -m | sed -n '/Mem:/s/ \+/ /gp' | cut -d' ' -f 2
# NAS RAM Used
- platform: command_line
  name: nas_mem_used
  unit_of_measurement: 'kB'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> free -m | sed -n '/buffers:/s/ \+/ /gp' | cut -d' ' -f 3
# NAS RAM Free
- platform: command_line
  name: nas_mem_free
  unit_of_measurement: 'kB'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> free -m | sed -n '/buffers:/s/ \+/ /gp' | cut -d' ' -f 4
# NAS RAM Cached
- platform: command_line
  name: nas_mem_cached
  unit_of_measurement: 'kB'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> cat /proc/meminfo | sed -n '/Cached/s/ \+/ /gp' | head -n 1 | cut -d' ' -f 2
# NAS Swap Total
- platform: command_line
  name: nas_swap_tot
  unit_of_measurement: 'kB'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> free -m | sed -n '/Swap/s/ \+/ /gp' | cut -d' ' -f 2
# NAS Swap Free
- platform: command_line
  name: nas_swap_free
  unit_of_measurement: 'kB'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> free -m | sed -n '/Swap/s/ \+/ /gp' | cut -d' ' -f 4
# NAS Swap Used
- platform: command_line
  name: nas_swap_used
  unit_of_measurement: 'kB'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> free -m | sed -n '/Swap/s/ \+/ /gp' | cut -d' ' -f 3
# NAS Swap Cached
- platform: command_line
  name: nas_swap_cached
  unit_of_measurement: 'kB'
  command: ssh -i <path_to_private_key_file> -o StrictHostKeyChecking=no -q <ssh_user>@<device_ip_or_hostname> cat /proc/meminfo | sed -n '/SwapCached/s/ \+/ /gp' | cut -d' ' -f 3

# Some derived values
- platform: template
  sensors:
    nas_cpu_perc_used:
      friendly_name: NAS CPU Usage
      value_template: "{{ (100 - states('sensor.nas_cpu_idle')|float) | round(1) }}"
      unit_of_measurement: '%'
    nas_ram_perc_used:
      friendly_name: NAS RAM Usage
      value_template: "{{ ((states('sensor.nas_mem_used')|int / states('sensor.nas_mem_tot')|int) * 100) | round(1) }}"
      unit_of_measurement: '%'
    nas_swap_perc_used:
      friendly_name: NAS Swap Usage
      value_template: "{{ ((states('sensor.nas_swap_used')|int / states('sensor.nas_swap_tot')|int) * 100) | round(1) }}"
      unit_of_measurement: '%'

Edit:

  • Added sensors
  • I had a quick look at the WD MyCloud API’s and there’s nothing there (that I can see) about getting this kind of information from the device, rather it’s more about file handling, geared at application integration.
2 Likes

I would definately like something like that. A’ve messed about it in the past and my solution the vas to have a script running that spits out the values in a file located in a a share on the MyCloud Mirror, that can then be retrieved by wahtever … it would be nice to get an integration for this.

Wouldn’t it be possible to automate that via crontab with an @reboot entry?

You’d think, wouldn’t you? Except that WD have thought of that, and - in a frenzy of XML standard breaking - have crippled configuration of locked down the cron as well.

However I have come up with an alternative trick, which avoids the need for ssh, but does need some minor manual intervention at each reboot.

  1. Logon as the ssh user.
  2. mkdir /mnt/HD/HD_a2/Nas_Prog/stats
  3. ln -s /mnt/HD/HD_a2/Nas_Prog/stats /var/www/stats

So

  • That’s the ‘stats’ folder now available at http://url_of_nas/stats.
  • The ‘stats’ folder and it’s contents are persistent, but you have to redo step 3 at every reboot. A pain, but substantially easier than dealing with the intracacies of ssh.

Next we need some content, preferrably serving JSON. The following are a version of the ssh files that came before:

.htaccess:

php_flag apc.cache_by_default Off

Disabling the apc cache is essential, unless you want the same stats each time you query.
UPDATE: The .htaccess file is not required for OS5.

disk.php

<?php
  $rtn = array();

  $cmd = "df | sed -n '/HD_a2/s/ \+/ /gp' | cut -d' ' -f 2";
  // Execute the command, and get the result from the returned array
  exec($cmd, $disktotres, $int);
  $rtn["disk"]["kB"]["total"] = $disktotres[0];

  $cmd = "df | sed -n '/HD_a2/s/ \+/ /gp' | cut -d' ' -f 3";
  // Execute the command, and get the result from the returned array
  exec($cmd, $diskusedres, $int);
  $rtn["disk"]["kB"]["used"] = $diskusedres[0];

  $cmd = "df | sed -n '/HD_a2/s/ \+/ /gp' | cut -d' ' -f 4";
  // Execute the command, and get the result from the returned array
  exec($cmd, $diskfreeres, $int);
  $rtn["disk"]["kB"]["free"] = $diskfreeres[0];

  $cmd = "df | sed -n '/HD_a2/s/ \+/ /gp' | cut -d' ' -f 5";
  // Execute the command, and get the result from the returned array
  exec($cmd, $diskpusedres, $int);
  $pctused = str_replace('%','',$diskpusedres[0]);
  $rtn["disk"]["percent"]["used"] = str_replace('%','',$pctused);
  $rtn["disk"]["percent"]["free"] = 100 - $pctused;

  // Return to the client
  echo json_encode($rtn, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK);
  // {"disk":{"kB":{"total":3837326424,"used":744981880,"free":3053341972},"percent":{"used":20,"free":80}}}
?>

memory.php

<?php
  $rtn = array();

  $cmd = "cat /proc/meminfo | sed -n '/MemTotal:/s/ \+/ /gp' | cut -d' ' -f 2";
  // Execute the command, and get the result from the returned array
  exec($cmd, $memtotres, $int);
  $rtn["memory"]["total"] = $memtotres[0];

  $cmd = "cat /proc/meminfo | sed -n '/MemFree:/s/ \+/ /gp' | cut -d' ' -f 2";
  // Execute the command, and get the result from the returned array
  exec($cmd, $memfreeres, $int);
  $rtn["memory"]["free"] = $memfreeres[0];

  $cmd = "cat /proc/meminfo | sed -n '/Buffers:/s/ \+/ /gp' | cut -d' ' -f 2";
  // Execute the command, and get the result from the returned array
  exec($cmd, $membufres, $int);
  $rtn["memory"]["buffered"] = $membufres[0];

  $cmd = "cat /proc/meminfo | sed -n '/Cached:/s/ \+/ /gp' | head -n 1 | cut -d' ' -f 2";
  // Execute the command, and get the result from the returned array
  exec($cmd, $memcachres, $int);
  $rtn["memory"]["cached"] = $memcachres[0];

  $cmd = "free -m | sed -n '/Swap/s/ \+/ /gp' | cut -d' ' -f 2";
  // Execute the command, and get the result from the returned array
  exec($cmd, $swaptotres, $int);
  $rtn["swap"]["total"] = $swaptotres[0];

  $cmd = "free -m | sed -n '/Swap/s/ \+/ /gp' | cut -d' ' -f 4";
  // Execute the command, and get the result from the returned array
  exec($cmd, $swapfreeres, $int);
  $rtn["swap"]["free"] = $swapfreeres[0];

  $cmd = "free -m | sed -n '/Swap/s/ \+/ /gp' | cut -d' ' -f 3";
  // Execute the command, and get the result from the returned array
  exec($cmd, $swapusedres, $int);
  $rtn["swap"]["used"] = $swapusedres[0];

  $cmd = "cat /proc/meminfo | sed -n '/SwapCached/s/ \+/ /gp' | cut -d' ' -f 2";
  // Execute the command, and get the result from the returned array
  exec($cmd, $swapcachres, $int);
  $rtn["swap"]["cached"] = $swapcachres[0];

  // Return to the client
  echo json_encode($rtn, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK);
  // {"memory":{"total":2084352,"free":907360,"buffered":165088,"cached":554944},"swap":{"total":2097056,"free":2097056,"used":0,"cached":0}}
?>

nas.php

<?php
  $rtn = array();

  $cmd = "/usr/sbin/fan_control -g 0";
  // Execute the command, and get the result from the returned array
  exec($cmd, $fanres, $int);
  //$rtn["res"] = $fanres;
  $rtn["temp"]["board"] = explode(" ", $fanres[0])[3];
  $rtn["temp"]["hd0"] = explode("=", $fanres[1])[1];
  $rtn["temp"]["hd1"] = explode("=", $fanres[2])[1];
  $rtn["temp"]["hd2"] = explode("=", $fanres[3])[1];
  $rtn["temp"]["hd3"] = explode("=", $fanres[4])[1];
  $rtn["temp"]["cpu"] = explode("=", $fanres[5])[1];

  $cmd = "/usr/local/sbin/getSmartStatus.sh";
  // Execute the command, and get the result from the returned array
  exec($cmd, $smtres, $int);
  $rtn["smart"] = $smtres[0];


  // Get the old software version
  $cmd = "cat /etc/NAS_CFG/config.xml | tr -d '\n' | tr -d '\t'";
  exec($cmd, $confxmlread, $int);
  $confxmlfile = '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>'.$confxmlread[0];
  // Replace invalid XML tags <1> through to <5>
  for ($cnt = 1; $cnt < 6; $cnt++){
    $confxmlfile = str_replace("<".$cnt.">", "<cron_".$cnt.">", $confxmlfile);
    $confxmlfile = str_replace("</".$cnt.">", "</cron_".$cnt.">", $confxmlfile);
  }
  $confxmlres = simplexml_load_string($confxmlfile);
  $confxmlarr = get_object_vars($confxmlres);
  // Get the current firmware version
  $rtn["fw"]["current"] = $confxmlarr["sw_ver_1"];


  // Get the new software version
  $cmd = "cat /tmp/upgrade_count";
  exec($cmd, $newfw, $int);
  $newfw = $newfw[0];
  // Set a default
  $rtn["fw"]["new"] = $newfw;


  // Work out if it's the latest version
  if ($rtn["fw"]["current"] <> $rtn["fw"]["new"]) {
    $rtn["fw"]["status"] = "Upgrade to ".$rtn["fw"]["new"];
  }


  // CPU usage
  $cmd = "/usr/sbin/mpstat | sed -n '/all/s/ \+/ /gp' | cut -d' ' -f 12 | sed 's/%//g'";
  // Execute the command, and get the result from the returned array
  exec($cmd, $mpres, $int);
  $rtn["cpu"]["idle"] = $mpres[0];
  $rtn["cpu"]["used"] = 100 - $mpres[0];

  // $cmd = "fan_control -g 4 | cut -d' ' -f 4";
  $cmd = "cat /tmp/fan_rpm";
  // Execute the command, and get the result from the returned array
  exec($cmd, $fanrpmres, $int);
  $rtn["fan"]["rpm"] = $fanrpmres[0];

  // Return to the client
  echo json_encode($rtn, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK);
?>

storage.php

<?php
  $rtn = array();

  $cmd = "cat /tmp/storage_usage.xml";
  exec($cmd, $storagexml, $int);

  $storageres = simplexml_load_string($storagexml[0]);
  $storagearr = get_object_vars($storageres);
  $rtn["storage"]["unit"] = 'kB';
  $rtn["storage"]["size"] = $storagearr['size'] / 1024;
  $rtn["storage"]["usage"] = $storagearr['usage'] / 1024;
  $rtn["storage"]["video"] = $storagearr['video'] / 1024;
  $rtn["storage"]["photos"] = $storagearr['photos'] / 1024;
  $rtn["storage"]["music"] = $storagearr['music'] / 1024;
  $rtn["storage"]["other"] = $storagearr['other'] / 1024;

  // Return to the client
  echo json_encode($rtn, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK);
?>

Now that’s out of the way, it’s over to the Home Assistant box. Here, Home Assistant is installed on top of the Raspberry Pi OS, so I regret that, if this does not work for you, you’ll have to find your own way using the tools that are available in HASS OS, or whatever other OS you have chosen to run.

Here crontab is used to call a script to call curl to get a set of JSON files to the Home Assistant box. This gets around the ridiculously small 255 character limit of the REST Sensor tool in Home Assistant.

Crontab of homeassistant user: Every two minutes, reach out to the NAS for stats.

*/2 * * * * /home/homeassistant/bin/nas_stats.sh

The files are copied to .tmp, then renamed, to avoid timing errors (copying a completed file is instantaneous, compared to the time to arrive over http, and the sensors in Home Assistant really don’t like incomplete json!).

/home/homeassistant/bin/nas_stats.sh

#!/bin/bash
mkdir -p /home/homeassistant/.homeassistant/files
cd /home/homeassistant/.homeassistant/files
# Get the disk usage of my_nas
curl http://url_of_nas/stats/disk.php > my_nas_disk.json.tmp
rm my_nas_disk.json
mv my_nas_disk.json.tmp my_nas_disk.json
# Get the memory & swap usage of my_nas
curl http://url_of_nas/stats/memory.php > my_nas_memory.json.tmp
rm my_nas_memory.json
mv my_nas_memory.json.tmp my_nas_memory.json
# Get the board sensors of my_nas
curl http://url_of_nas/stats/nas.php > my_nas_nas.json.tmp
rm my_nas_nas.json
mv my_nas_nas.json.tmp my_nas_nas.json
# Get the storage usage of my_nas
curl http://url_of_nas/stats/storage.php > my_nas_storage.json.tmp
rm my_nas_storage.json
mv my_nas_storage.json.tmp my_nas_storage.json

Finally, place this file in the packages area of your Home Assistant:

nas.yaml

# /config/packages/nas.yaml

###################################
############ NAS STATS ############
###################################
# A cron job runs curl, which gets a file from  http://url_of_nas/stats/<something>.php
#
sensor:
- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_nas.json
  name: nas_cpu_temp
  value_template: "{{ value_json.temp.cpu }}"
  unit_of_measurement: '°C'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_nas.json
  name: nas_board_temp
  value_template: "{{ value_json.temp.board }}"
  unit_of_measurement: '°C'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_nas.json
  name: nas_hd0_temp
  value_template: "{{ value_json.temp.hd0 }}"
  unit_of_measurement: '°C'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_nas.json
  name: nas_hd1_temp
  value_template: "{{ value_json.temp.hd1 }}"
  unit_of_measurement: '°C'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_nas.json
  name: nas_hd2_temp
  value_template: "{{ value_json.temp.hd2 }}"
  unit_of_measurement: '°C'
  
- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_nas.json
  name: nas_hd3_temp
  value_template: "{{ value_json.temp.hd3 }}"
  unit_of_measurement: '°C'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_nas.json
  name: nas_smart_status
  value_template: "{{ value_json.smart }}"

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_nas.json
  name: nas_firmware_current
  value_template: "{{ value_json.fw.current }}"

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_nas.json
  name: nas_firmware_new
  value_template: "{{ value_json.fw.new }}"

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_nas.json
  name: nas_firmware_status
  value_template: "{{ value_json.fw.status }}"

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_nas.json
  name: nas_fan_rpm
  value_template: "{{ value_json.fan.rpm }}"
  unit_of_measurement: 'rpm'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_disk.json
  name: nas_disk_space_total
  value_template: "{{ value_json.disk.kB.total }}"
  unit_of_measurement: 'kB'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_disk.json
  name: nas_disk_space_used
  value_template: "{{ value_json.disk.kB.used }}"
  unit_of_measurement: 'kB'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_disk.json
  name: nas_disk_space_free
  value_template: "{{ value_json.disk.kB.free }}"
  unit_of_measurement: 'kB'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_disk.json
  name: nas_disk_perc_used
  value_template: "{{ value_json.disk.percent.used }}"
  unit_of_measurement: '%'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_disk.json
  name: nas_disk_perc_free
  value_template: "{{ value_json.disk.percent.free }}"
  unit_of_measurement: '%'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_nas.json
  name: nas_cpu_idle
  value_template: "{{ value_json.cpu.idle }}"
  unit_of_measurement: '%'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_nas.json
  name: nas_cpu_used
  value_template: "{{ value_json.cpu.used }}"
  unit_of_measurement: '%'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_storage.json
  name: nas_storage_size
  value_template: "{{ value_json.storage.size }}"
  unit_of_measurement: 'kB'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_storage.json
  name: nas_storage_usage
  value_template: "{{ value_json.storage.usage }}"
  unit_of_measurement: 'kB'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_storage.json
  name: nas_storage_video
  value_template: "{{ value_json.storage.video }}"
  unit_of_measurement: 'kB'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_storage.json
  name: nas_storage_photos
  value_template: "{{ value_json.storage.photos }}"
  unit_of_measurement: 'kB'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_storage.json
  name: nas_storage_music
  value_template: "{{ value_json.storage.music }}"
  unit_of_measurement: 'kB'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_storage.json
  name: nas_storage_other
  value_template: "{{ value_json.storage.other }}"
  unit_of_measurement: 'kB'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_memory.json
  name: nas_mem_tot
  value_template: "{{ value_json.memory.total }}"
  unit_of_measurement: 'bytes'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_memory.json
  name: nas_mem_free
  value_template: "{{ value_json.memory.free }}"
  unit_of_measurement: 'bytes'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_memory.json
  name: nas_mem_buffered
  value_template: "{{ value_json.memory.buffered }}"
  unit_of_measurement: 'bytes'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_memory.json
  name: nas_mem_cached
  value_template: "{{ value_json.memory.cached }}"
  unit_of_measurement: 'bytes'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_memory.json
  name: nas_swap_tot
  value_template: "{{ value_json.swap.total }}"
  unit_of_measurement: 'bytes'

- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_memory.json
  name: nas_swap_free
  value_template: "{{ value_json.swap.free }}"
  unit_of_measurement: 'bytes'
  
- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_memory.json
  name: nas_swap_used
  value_template: "{{ value_json.swap.used }}"
  unit_of_measurement: 'bytes'
  
- platform: file
  file_path: /home/homeassistant/.homeassistant/files/my_nas_memory.json
  name: nas_swap_cached
  value_template: "{{ value_json.swap.cached }}"
  unit_of_measurement: 'bytes'

###################################
############ NAS STATS ############
###################################
- platform: template
  sensors:
    nas_ram_perc_used:
      friendly_name: NAS RAM Usage
      value_template: "{{ ( 100 * (states('sensor.nas_mem_tot')|int - states('sensor.nas_mem_free')|int - states('sensor.nas_mem_buffered')|int - states('sensor.nas_mem_cached')|int ) / states('sensor.nas_mem_tot')|int) | round(1) }}"
      unit_of_measurement: '%'
    nas_swap_perc_used:
      friendly_name: NAS Swap Usage
      value_template: "{{ ((states('sensor.nas_swap_used')|int / states('sensor.nas_swap_tot')|int) * 100) | round(1) }}"
      unit_of_measurement: '%'

# Average Fan RPM
- platform: filter
  name: "nas_fan_rpm_smooth"
  entity_id: sensor.nas_fan_rpm
  filters:
    - filter: lowpass
      time_constant: 10
      precision: 2

Ok, I think that’s everything I have. I’m not claiming the stats are all correct - in fact at least some of them won’t be, my knowledge of the WD innards and Bash is enough to be dangerous, but certainly not in-depth - so I’m happy to stand corrected.

Hey Guys,
Thank you very much for the code.

But wouldn’t it be way easier to just use SNMP for the Data and put it on the Dashboard?
I know it’s a old protocol but it should work just fine.

I say lead us to the light brother cnoob404. If you manage to get it working, i’m sure a short tutorial would be appreciated. It would be nice to have something that is persistent across reboots.

I’ve looked into this before, and my small WD MyCloud doesn’t support SNMP. It might be possible to get an agent installed manually, but there is very little to no info on this. I’m guessing you have a device that has a setting for enabling SNMP?

Hey Guys,

I just found out, in the middle of coding…, that someone already did this:

But if you want to find your own OID´s just find them with iReasoning MIB Browser.
Another great idea is PRTG from Paessler. With that thing, you can monitor almost everything and there is a way to put it in your Home Assistant.

But for now, this is how I wrote my sensor for my Free Disk Space:

#SNMP Sensor My Cloud
  - platform: snmp
    name: "MyCloud Free Disk Space"
    host: 192.168.178.30 #(the IP of your NAS)
    baseoid: 1.3.6.1.4.1.5127.1.1.1.6.1.9.1.6.1
    community: 'public'
    version: "2c"
    value_template: "{{ value.replace('G','') }}"
    unit_of_measurement: "GB"
    accept_errors: true
    scan_interval: "500"

There is no need for installing a “device_tracker” for SNMP.

For the Single HDD, I´m sorry, I can’t help you with that. But you can try PRTG on Auto-Discovery.

I hope I helped you with that.

Edit:

I did a little bit of configuration with the Sensors:

#SNMP Sensor Jan Cloud
  - platform: snmp
    name: 'NAS Free Space'
    host: 192.168.178.30
    baseoid: 1.3.6.1.4.1.5127.1.1.1.6.1.9.1.6.1
    community: 'public'
    version: "2c"
    value_template: "{{ value.replace('G','') }}"
    unit_of_measurement: "GB"
    accept_errors: true
    scan_interval: 300

  - platform: snmp
    name: 'NAS System Temperature'
    host: 192.168.178.30
    baseoid: 1.3.6.1.4.1.5127.1.1.1.6.1.7.0
    community: 'public'
    version: '2c'
    unit_of_measurement: '°C'
    value_template: "{{ value.split(' ')[0].split(':')[1] }}"
    scan_interval: 60

  - platform: snmp
    name: 'NAS Disk 1 Temperature'
    host: 192.168.178.30
    baseoid: 1.3.6.1.4.1.5127.1.1.1.6.1.10.1.5.1
    community: 'public'
    version: '2c'
    unit_of_measurement: '°C'
    value_template: "{{ value.split(':')[1] }}"
    scan_interval: 60

  - platform: snmp
    name: 'NAS Disk 2 Temperature'
    host: 192.168.178.30
    baseoid: 1.3.6.1.4.1.5127.1.1.1.6.1.10.1.5.1
    community: 'public'
    version: '2c'
    unit_of_measurement: '°C'
    value_template: "{{ value.split(':')[1] }}"
    scan_interval: 60

  - platform: snmp
    name: 'NAS Disk 3 Temperature'
    host: 192.168.178.30
    baseoid: 1.3.6.1.4.1.5127.1.1.1.6.1.10.1.5.1
    community: 'public'
    version: '2c'
    unit_of_measurement: '°C'
    value_template: "{{ value.split(':')[1] }}"
    scan_interval: 60

  - platform: snmp
    name: 'NAS Disk 4 Temperature'
    host: 192.168.178.30
    baseoid: 1.3.6.1.4.1.5127.1.1.1.6.1.10.1.5.1
    community: 'public'
    version: '2c'
    unit_of_measurement: '°C'
    value_template: "{{ value.split(':')[1] }}"
    scan_interval: 60

  - platform: snmp
    name: 'NAS Fan Status'
    host: 192.168.178.30
    baseoid: 1.3.6.1.4.1.5127.1.1.1.6.1.8.0
    community: 'public'
    version: '2c'
    value_template: "{{ value.replace('fan0: running','On')  }}"
    scan_interval: 60

  - platform: snmp
    name: 'NAS Size'
    host: 192.168.178.30
    baseoid: 1.3.6.1.4.1.5127.1.1.1.6.1.9.1.5.1
    community: 'public'
    version: '2c'
    value_template: "{{ value.replace('T','') }}"
    unit_of_measurement: 'TB'
    scan_interval: 300

And for the Lovelace we need another Fan sensors.

type: entities
entities:
  - entity: sensor.nas_free_space
  - entity: sensor.nas_fan_status
    name: Fan
  - entity: sensor.nas_system_temperature
    name: System Temperature
  - entity: sensor.nas_disk_1_temperature
    name: Disk 1 Temperature
  - entity: sensor.nas_disk_2_temperature
    name: Disk 2 Temperature
  - entity: sensor.nas_disk_3_temperature
    name: Disk 3 Temperature
  - entity: sensor.nas_disk_4_temperature
    name: Disk 4 Temperature
title: WD EX4100 NAS
show_header_toggle: false
state_color: true

But I still have some problems with the system temperature sensor. Home Assistant won’t separate the strings…

 value_template: "{{ value.split(' ')[0].split(':')[1] }}"
1 Like

how did you turn on the smtp on the mybook?

That´s the same edge I stumbled upon:
Issue seems to be, that ninja2 has an issue with ‘tab’ (0x09) (at least my EX2Ultra); if you copy the system temp. value from a MIB browser, you can see that it is not only a ‘space’. I asked in another thread, and even the ninja gurus said it would be quite complicated to do a workaround.

I used the above and got this working. Using iReasoning I found my OIDs (Which were off by one digit compared to yours). The only issue I have on my MyCloud EX2 Ultra is the system temperature. My OID is 1.3.6.1.4.1.5127.1.1.1.8.1.8.0, and in iReasoning it gets as: “Centigrade:43 Fahrenheit:109”.
However in HA, I dumbed it down to this (since I couldn’t get it to work):

 - platform: snmp
     name: "NAS System Temperature"
     host: 192.168.x.y
     baseoid: 1.3.6.1.4.1.5127.1.1.1.8.1.7.0
     community: !secret SNMP
     version: "2c"
     #unit_of_measurement: "°F"
     #value_template: "{{ value.split('Fahrenheit:')[1] }}"
     scan_interval: 60

And the value I get on it when I look at it in Lovelace is:
1,816,998,406,599,389,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000
I’m assuming you may have a similar issue which is why HA isn’t separating the strings for you. (Try removing the value_template and just looking at the value as-is to see what SNMP is returning).
I’ve checked this value at different times when iReasoning is showing different temperatures, and it does not change. So it does not look like an encoding issue of the data.
Best guess is it’s the SNMP integration stumbling over the tab in the return value and just spitting out a big number.

If anyone has any idea on what to do with that, I’m open to suggestions.

I’m working on the System Temperature issue. It returns Hexadecimal. I ran it through a Hex to String conversion and it converted to the values we expect. Now we need to find a way to do that conversion in HA. The last 6 hex characters convert to the Fahrenheit value which is what I want. So we should be able to substring the value and then we’re back to the hex conversion issue.

I’m striking out figuring out a way to convert from Hex to ASCII. I’m going to try a command-line function using snmpget and then parse that result.

I’m happy to have a look, but could you paste a text version of that screenshot, please?

Sure.

The SNMP sensor returns a Hex value of 0x43656e746967726164653a3437200946616872656e686569743a313136

After stripping off the 0x, the ASCII conversion of it equates to “Centigrade:47 Fahrenheit:116”.

I can get by with just converting the last 6 Hex characters since all I want is the Fahrenheit value but something generic could be more useful to others.