Western Digital My Cloud

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.

This doesn’t work. I installed the snmp package in my HA terminal window but I learned that’s not permanent after a reboot. Otherwise, that would have worked.

I’m a little further along now. I successfully installed the pyscript integration. I wrote a very simple service to convert an input parameter from HEX to ASCII. It works great with the Developer Tools if I manually pass the hex sensor value. Now I’m not sure how to pass the actual entity sensor value as a variable and get the result.

On my phone, but basically the idea would be:

{{ (int("0x31", base=16) - 48)*100 + (int("0x31", base=16) - 48)*10 + (int("0x36", base=16) - 48) }}

Replace the hex string parts by slicing the original string. Convert from base 16 and subtract 48 (ordinal value for ASCII character 0), etc.

Makes sense. Where would I do this?

I should clarify that I got the pyscript to convert from hex to ascii with the entity value. but I have no idea how to either set another variable with the service output using an automation or use the service output in a lovelace dashboard card.

I was thinking:
Create an Automation that runs every 5 mins.
The automation runs the service with the entity that has the hex value.
The service sets another entity value with the converted string.
Use that second entity in the dashboards.

This seems like a lot and I’m not sure I can set a second entity value. How would I manually create that entity? Sensor Template doesn’t make sense.

Could you perhaps clarify a bit more what you’re doing and where you are getting values from? The hex string: Is that the state of an SNMP sensor (trap)? Where is the Python script you’re referring to coming into the picture? Or are you just experimenting with a script (outside of HA) to parse the values?

You can’t “update” a sensor by setting a value from within HA if it’s set by another integration, neither can you add an attribute and value to it. I don’t know if you could do it via the API.

Personally, I’d just make a new template sensor where you can set the state and any attributes that you’d like all in one go based on the original sensor. You can control the icon, name and device class also there.

If you can give me the original sensor name I can type out a solution a bit later.

EDIT:

sensor:
  - platform: template
    sensors:
      wd_cloud_temp:
        friendly_name: "WD Cloud Temperature"
        unit_of_measurement: "°"
        value_template: "{{ (int(states('sensor.something')[-6:-4], base=16) - 48)*100 + (int(states('sensor.something')[-4:-2], base=16) - 48)*10 + (int(states('sensor.something')[-2:], base=16) - 48) }}"

Or:

template:
  - sensor:
      - name: "WD Cloud Temperature"
        unit_of_measurement: "°"
        state: "{{ (int(states('sensor.something')[-6:-4], base=16) - 48)*100 + (int(states('sensor.something')[-4:-2], base=16) - 48)*10 + (int(states('sensor.something')[-2:], base=16) - 48) }}"

Based on:

{% set sensor = '0x43656e746967726164653a3437200946616872656e686569743a313136' %}
{{ (int(sensor[-6:-4], base=16) - 48)*100 + (int(sensor[-4:-2], base=16) - 48)*10 + (int(sensor[-2:], base=16) - 48) }}
1 Like

Not sure why I didn’t think of a template sensor. I’m going to try that.