2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 12:49:34 +00:00

added: simple NVMe support

git-svn-id: https://svn.fhem.de/fhem/trunk@26656 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
hexenmeister 2022-11-05 19:10:11 +00:00
parent bbc263f486
commit c1107909d2

View File

@ -32,7 +32,7 @@ use warnings;
use JSON; use JSON;
use Data::Dumper; use Data::Dumper;
my $VERSION = "0.9.9"; my $VERSION = "0.9.9.2";
my $DEFAULT_INTERVAL = 60; # in minuten my $DEFAULT_INTERVAL = 60; # in minuten
@ -470,7 +470,7 @@ sub SMARTMON_getSmartDataReadings($$) {
# Bekannte Werte einspielen # Bekannte Werte einspielen
# per Referenz uebergeben! # per Referenz uebergeben!
my $done_map = SMARTMON_interpretKnownData($hash, \%{$dmap}, \%{$map}); my $done_map = SMARTMON_interpretKnownData($hash, \%{$dmap}, \%{$map});
my $cnt_oldage=0; my $cnt_oldage=0;
my $cnt_prefail=0; my $cnt_prefail=0;
my $sr = AttrVal($name, "show_raw", "0"); my $sr = AttrVal($name, "show_raw", "0");
@ -487,13 +487,18 @@ sub SMARTMON_getSmartDataReadings($$) {
# oder wenn explizit erwuenscht (Attribut show_raw) # oder wenn explizit erwuenscht (Attribut show_raw)
if(!defined($done_map->{$id}) || $sr eq "2") { if(!defined($done_map->{$id}) || $sr eq "2") {
my $m = $dmap->{$id}; my $m = $dmap->{$id};
my $rName = $m->{name}; if($m->{format} eq 0) {
#my $raw = $dmap->{$id}->{raw}; my $rName = $m->{name};
$map->{sprintf("%03d_%s",$id,$rName)} = #my $raw = $dmap->{$id}->{raw};
sprintf("Flag: %s Val: %s Worst: %s Thresh: %s ". $map->{sprintf("%03d_%s",$id,$rName)} =
"Type: %s Updated: %s When_Failed: %s Raw: %s", sprintf("Flag: %s Val: %s Worst: %s Thresh: %s ".
$m->{flag},$m->{value},$m->{worst},$m->{thresh},$m->{type}, "Type: %s Updated: %s When_Failed: %s Raw: %s",
$m->{updated},$m->{failed},$m->{raw}); $m->{flag},$m->{value},$m->{worst},$m->{thresh},$m->{type},
$m->{updated},$m->{failed},$m->{raw});
} else {
my $rName = $m->{name};
$map->{$id} = $m->{text};
}
} }
} }
} }
@ -520,7 +525,7 @@ sub SMARTMON_readDeviceData($%) {
my($k,$v) = split(/:\s*/,$line); my($k,$v) = split(/:\s*/,$line);
if(defined $v) { if(defined $v) {
$v = trim($v); $v = trim($v);
if($k eq "Device Model") { if(($k eq "Device Model") || ($k eq "Model Number")) {
$hash->{DEVICE_MODEL}=$v; $hash->{DEVICE_MODEL}=$v;
$map->{"deviceModel"}=$v if($sd eq '1'); $map->{"deviceModel"}=$v if($sd eq '1');
} }
@ -532,7 +537,7 @@ sub SMARTMON_readDeviceData($%) {
$hash->{DEVICE_FIRMWARE}=$v; $hash->{DEVICE_FIRMWARE}=$v;
$map->{"deviceFirmware"}=$v if($sd eq '1'); $map->{"deviceFirmware"}=$v if($sd eq '1');
} }
if($k eq "User Capacity") { if(($k eq "User Capacity") || ($k eq "Total NVM Capacity")) {
$hash->{DEVICE_CAPACITY}=$v; $hash->{DEVICE_CAPACITY}=$v;
$map->{"deviceCapacity"}=$v if($sd eq '1'); $map->{"deviceCapacity"}=$v if($sd eq '1');
} }
@ -616,6 +621,166 @@ sub SMARTMON_interpretKnownData($$$) {
$known->{"RC"}=1; $known->{"RC"}=1;
} }
# > NVMe
# smartctl 7.2 2020-12-30 r5155 [x86_64-linux-5.18.0-0.deb11.4-amd64] (local build)
# Copyright (C) 2002-20, Bruce Allen, Christian Franke, www.smartmontools.org
#
# === START OF SMART DATA SECTION ===
# SMART/Health Information (NVMe Log 0x02)
# Critical Warning: 0x00
# Temperature: 38 Celsius
# Available Spare: 100%
# Available Spare Threshold: 1%
# Percentage Used: 1%
# Data Units Read: 88.487 [45,3 GB]
# Data Units Written: 253.077 [129 GB]
# Host Read Commands: 1.006.924
# Host Write Commands: 19.046.809
# Controller Busy Time: 6
# Power Cycles: 45
# Power On Hours: 789
# Unsafe Shutdowns: 39
# Media and Data Integrity Errors: 0
# Error Information Log Entries: 67
# Warning Comp. Temperature Time: 0
# Critical Comp. Temperature Time: 0
# Temperature Sensor 1: 50 Celsius
# Temperature Sensor 2: 51 Celsius
# Temperature Sensor 3: 52 Celsius
# Temperature Sensor 4: 53 Celsius
# Temperature Sensor 5: 54 Celsius
# Temperature Sensor 6: 55 Celsius
# Temperature Sensor 7: 56 Celsius
# Temperature Sensor 8: 57 Celsius
if($dmap->{"Power On Hours"}) {
my $poh = $dmap->{"Power On Hours"}->{text};
$map->{power_on_hours} = $poh;
my $poht = $poh =~ s/\.//r;
$map->{power_on_text} = SMARTMON_hour2Dauer($poht);
$known->{"Power On Hours"}=1;
}
if($dmap->{"Power Cycles"}) {
$map->{power_cycle_count} = $dmap->{"Power Cycles"}->{text};
$known->{"Power Cycles"}=1;
}
if($dmap->{"Temperature"}) {
my($tv, $tu) = split(/\s+/, trim($dmap->{"Temperature"}->{text}));
$map->{temperature} = $tv;
$known->{"Temperature"}=1;
}
if($dmap->{"Temperature Sensor 1"}) {
my($tv, $tu) = split(/\s+/, trim($dmap->{"Temperature Sensor 1"}->{text}));
$map->{temperature1} = $tv;
$known->{"Temperature Sensor 1"}=1;
}
if($dmap->{"Temperature Sensor 2"}) {
my($tv, $tu) = split(/\s+/, trim($dmap->{"Temperature Sensor 2"}->{text}));
$map->{temperature2} = $tv;
$known->{"Temperature Sensor 2"}=1;
}
if($dmap->{"Temperature Sensor 3"}) {
my($tv, $tu) = split(/\s+/, trim($dmap->{"Temperature Sensor 3"}->{text}));
$map->{temperature3} = $tv;
$known->{"Temperature Sensor 3"}=1;
}
if($dmap->{"Temperature Sensor 4"}) {
my($tv, $tu) = split(/\s+/, trim($dmap->{"Temperature Sensor 4"}->{text}));
$map->{temperature4} = $tv;
$known->{"Temperature Sensor 4"}=1;
}
if($dmap->{"Temperature Sensor 5"}) {
my($tv, $tu) = split(/\s+/, trim($dmap->{"Temperature Sensor 5"}->{text}));
$map->{temperature5} = $tv;
$known->{"Temperature Sensor 5"}=1;
}
if($dmap->{"Temperature Sensor 6"}) {
my($tv, $tu) = split(/\s+/, trim($dmap->{"Temperature Sensor 6"}->{text}));
$map->{temperature6} = $tv;
$known->{"Temperature Sensor 6"}=1;
}
if($dmap->{"Temperature Sensor 7"}) {
my($tv, $tu) = split(/\s+/, trim($dmap->{"Temperature Sensor 7"}->{text}));
$map->{temperature7} = $tv;
$known->{"Temperature Sensor 7"}=1;
}
if($dmap->{"Temperature Sensor 8"}) {
my($tv, $tu) = split(/\s+/, trim($dmap->{"Temperature Sensor 8"}->{text}));
$map->{temperature8} = $tv;
$known->{"Temperature Sensor 8"}=1;
}
if($dmap->{"Critical Warning"}) {
$map->{critical_warning} = $dmap->{"Critical Warning"}->{text};
$known->{"Critical Warning"}=1;
}
if($dmap->{"Available Spare"}) {
$map->{available_spare} = $dmap->{"Available Spare"}->{text};
$known->{"Available Spare"}=1;
}
if($dmap->{"Available Spare Threshold"}) {
$map->{available_spare_threshold} = $dmap->{"Available Spare Threshold"}->{text};
$known->{"Available Spare Threshold"}=1;
}
if($dmap->{"Percentage Used"}) {
$map->{percentage_used} = $dmap->{"Percentage Used"}->{text};
$known->{"Percentage Used"}=1;
}
if($dmap->{"Data Units Read"}) {
$map->{data_units_read} = $dmap->{"Data Units Read"}->{text};
$known->{"Data Units Read"}=1;
}
if($dmap->{"Data Units Written"}) {
$map->{data_units_written} = $dmap->{"Data Units Written"}->{text};
$known->{"Data Units Written"}=1;
}
if($dmap->{"Host Read Commands"}) {
$map->{host_read_commands} = $dmap->{"Host Read Commands"}->{text};
$known->{"Host Read Commands"}=1;
}
if($dmap->{"Host Write Commands"}) {
$map->{host_write_commands} = $dmap->{"Host Write Commands"}->{text};
$known->{"Host Write Commands"}=1;
}
if($dmap->{"Controller Busy Time"}) {
$map->{controller_busy_time} = $dmap->{"Controller Busy Time"}->{text};
$known->{"Controller Busy Time"}=1;
}
if($dmap->{"Unsafe Shutdowns"}) {
$map->{unsafe_shutdowns} = $dmap->{"Unsafe Shutdowns"}->{text};
$known->{"Unsafe Shutdowns"}=1;
}
if($dmap->{"Media and Data Integrity Errors"}) {
$map->{media_and_data_integrity_errors} = $dmap->{"Media and Data Integrity Errors"}->{text};
$known->{"Media and Data Integrity Errors"}=1;
}
if($dmap->{"Error Information Log Entries"}) {
$map->{error_information_log_entries} = $dmap->{"Error Information Log Entries"}->{text};
$known->{"Error Information Log Entries"}=1;
}
if($dmap->{"Warning Comp. Temperature Time"}) {
$map->{warning_comp_temperature_time} = $dmap->{"Warning Comp. Temperature Time"}->{text};
$known->{"Warning Comp. Temperature Time"}=1;
}
if($dmap->{"Critical Comp. Temperature Time"}) {
$map->{critical_comp_temperature_time} = $dmap->{"Critical Comp. Temperature Time"}->{text};
$known->{"Critical Comp. Temperature Time"}=1;
}
return $known; return $known;
} }
@ -657,6 +822,45 @@ sub SMARTMON_readSmartData($;$) {
my $param=""; my $param="";
if($hash->{PARAMETERS}) {$param=" ".$hash->{PARAMETERS};} if($hash->{PARAMETERS}) {$param=" ".$hash->{PARAMETERS};}
my ($r, @dev_data) = SMARTMON_execute($hash, "sudo smartctl -A".$param." ".$hash->{DEVICE}); my ($r, @dev_data) = SMARTMON_execute($hash, "sudo smartctl -A".$param." ".$hash->{DEVICE});
### TEST
#SMARTMON_Log($hash, 1, "TEST device SMART data !!!");
#my $r = "TEST";
#my @dev_data = (
#"smartctl 7.2 2020-12-30 r5155 [x86_64-linux-5.18.0-0.deb11.4-amd64] (local build)",
#"Copyright (C) 2002-20, Bruce Allen, Christian Franke, www.smartmontools.org",
#"",
#"=== START OF SMART DATA SECTION ===",
#"SMART/Health Information (NVMe Log 0x02)",
#"Critical Warning: 0x00",
#"Temperature: 38 Celsius",
#"Available Spare: 100%",
#"Available Spare Threshold: 1%",
#"Percentage Used: 1%",
#"Data Units Read: 88.487 [45,3 GB]",
#"Data Units Written: 253.077 [129 GB]",
#"Host Read Commands: 1.006.924",
#"Host Write Commands: 19.046.809",
#"Controller Busy Time: 6",
#"Power Cycles: 45",
#"Power On Hours: 91.999.999",
#"Unsafe Shutdowns: 39",
#"Media and Data Integrity Errors: 0",
#"Error Information Log Entries: 67",
#"Warning Comp. Temperature Time: 0",
#"Critical Comp. Temperature Time: 0",
#"Temperature Sensor 1: 50 Celsius",
#"Temperature Sensor 2: 51 Celsius",
#"Temperature Sensor 3: 52 Celsius",
#"Temperature Sensor 4: 53 Celsius",
#"Temperature Sensor 5: 54 Celsius",
#"Temperature Sensor 6: 55 Celsius",
#"Temperature Sensor 7: 56 Celsius",
#"Temperature Sensor 8: 57 Celsius",
#"Testwert: 38 Papageien"
#);
### TEST
SMARTMON_Log($hash, 5, "device SMART data: ".Dumper(@dev_data)); SMARTMON_Log($hash, 5, "device SMART data: ".Dumper(@dev_data));
if(defined($r)) {$map->{"RC"}->{raw} = $r;} if(defined($r)) {$map->{"RC"}->{raw} = $r;}
if(defined($dev_data[0])) { if(defined($dev_data[0])) {
@ -682,6 +886,23 @@ sub SMARTMON_readSmartData($;$) {
$map->{$d_id}->{updated} = $d_updated; $map->{$d_id}->{updated} = $d_updated;
$map->{$d_id}->{failed} = $d_when_failed; $map->{$d_id}->{failed} = $d_when_failed;
$map->{$d_id}->{raw} = $d_raw_value; $map->{$d_id}->{raw} = $d_raw_value;
$map->{$d_id}->{format} = 0;
}
}
}
} elsif (scalar(@dev_data)>0 && $dev_data[0]=~m/NVMe/) {
shift @dev_data;
while(scalar(@dev_data)>0) {
my ($d_attr_name, $d_value) = split(/:/, trim($dev_data[0]));
shift @dev_data;
$d_attr_name = trim($d_attr_name);
$d_value = trim($d_value);
if(!defined($include) || defined($include->{$d_attr_name})) {
if(defined($d_attr_name)) {
$map->{$d_attr_name}->{name} = $d_attr_name;
$map->{$d_attr_name}->{text} = $d_value;
$map->{$d_attr_name}->{format} = 1;
} }
} }
} }