lmsensors 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +2 -0
- data/FMAPPER.md +20 -0
- data/LICENSE.txt +165 -0
- data/README.md +156 -0
- data/ext/lmsensors_base/extconf.rb +9 -0
- data/lib/lmsensors.rb +13 -0
- data/lib/lmsensors/feature.rb +11 -0
- data/lib/lmsensors/features/abs_feature.rb +85 -0
- data/lib/lmsensors/features/alarm.rb +38 -0
- data/lib/lmsensors/features/beep.rb +33 -0
- data/lib/lmsensors/features/current.rb +69 -0
- data/lib/lmsensors/features/fan.rb +52 -0
- data/lib/lmsensors/features/humidity.rb +35 -0
- data/lib/lmsensors/features/power.rb +80 -0
- data/lib/lmsensors/features/temp.rb +69 -0
- data/lib/lmsensors/features/voltage.rb +69 -0
- data/lib/lmsensors/lm_constants.rb +193 -0
- data/lib/lmsensors/lmsensors.rb +33 -0
- data/lib/lmsensors/sensors/abssensor.rb +151 -0
- data/lib/lmsensors/sensors/sensor.rb +148 -0
- data/lib/lmsensors/sensors/sensorspawner.rb +77 -0
- data/lib/lmsensors/version.rb +8 -0
- data/lib/lmsensors_base/lmsensors_base.so +0 -0
- metadata +96 -0
@@ -0,0 +1,193 @@
|
|
1
|
+
# lib/lmsensors/lm_constants.rb
|
2
|
+
|
3
|
+
# Require the base implementation
|
4
|
+
require_relative "../lmsensors_base/lmsensors_base"
|
5
|
+
|
6
|
+
# :nodoc: Constants for the LmSensors module
|
7
|
+
module LmSensors
|
8
|
+
##
|
9
|
+
# The default feature map method maps the feature
|
10
|
+
# type to the subclass that will be used to handle
|
11
|
+
# formatting and analytic post-processing.
|
12
|
+
DEF_FMAP = lambda do |name, f_obj|
|
13
|
+
case f_obj[:type]
|
14
|
+
when SF_IN
|
15
|
+
Feature::Voltage.new name, f_obj
|
16
|
+
when SF_CURR
|
17
|
+
Feature::Current.new name, f_obj
|
18
|
+
when SF_POWER
|
19
|
+
Feature::Power.new name, f_obj
|
20
|
+
when SF_TEMP
|
21
|
+
Feature::Temp.new name, f_obj
|
22
|
+
when SF_FAN
|
23
|
+
Feature::Fan.new name, f_obj
|
24
|
+
when SF_HUMIDITY
|
25
|
+
Feature::Humidity.new name, f_obj
|
26
|
+
when SF_INTRUSION
|
27
|
+
Feature::Alarm.new name, f_obj
|
28
|
+
when SF_BEEP_ENABLE
|
29
|
+
Feature::Beep.new name, f_obj
|
30
|
+
else
|
31
|
+
Feature::GenFeature.new name, f_obj
|
32
|
+
end
|
33
|
+
end # End default feature mapper
|
34
|
+
|
35
|
+
##
|
36
|
+
# CHK_BEEP uses the same formatting as the print_chip_beep_enable
|
37
|
+
# from the sensors program chips.c.
|
38
|
+
CHK_BEEP = lambda { |v| v < 0.5 ? "disabled" : "enabled" }
|
39
|
+
|
40
|
+
##
|
41
|
+
# CHK_ALARM uses the same formatting as the print_chip_intrusion
|
42
|
+
# from the sensors program chips.c.
|
43
|
+
CHK_ALARM = lambda { |v| v.zero? ? "OK" : "ALARM" }
|
44
|
+
|
45
|
+
##
|
46
|
+
# Index of units -- this will map the expected
|
47
|
+
# default units to any features. These are taken from
|
48
|
+
# the 'lm-sensors' headers, and I have exported the
|
49
|
+
# constants from the C-code to here. The names DIRECTLY
|
50
|
+
# correspond to the 'sensors_feature_type' enum, but
|
51
|
+
# they have been shortened from 'SENSORS_FEATURE_'
|
52
|
+
# to 'SF_'.
|
53
|
+
#
|
54
|
+
# This is, to the best of my ability, taken from the
|
55
|
+
# chips.c file, which has a header you can't seem to
|
56
|
+
# access from sensors.h.
|
57
|
+
UNITS = {
|
58
|
+
SF_IN => "V", # Volts
|
59
|
+
SF_FAN => "RPM", # RPM (fan)
|
60
|
+
SF_TEMP => "°C", # Degrees Celsius
|
61
|
+
SF_POWER => "W", # Watts
|
62
|
+
SF_ENERGY => "J", # Energy, Joules
|
63
|
+
SF_CURR => "A", # Current, Amps
|
64
|
+
SF_HUMIDITY => "% RH", # Humidity, percent
|
65
|
+
SF_MAX_MAIN => "",
|
66
|
+
# Skips here
|
67
|
+
SF_VID => "V", # Vid -- this is in Volts
|
68
|
+
SF_INTRUSION => CHK_ALARM, # Intrusion
|
69
|
+
SF_MAX_OTHER => "",
|
70
|
+
# Skips here, again
|
71
|
+
SF_BEEP_ENABLE => CHK_BEEP, # Beep enabled, true if gte 0.5
|
72
|
+
SF_MAX => "",
|
73
|
+
SF_UNKNOWN => "",
|
74
|
+
} # End default units enum
|
75
|
+
|
76
|
+
##
|
77
|
+
# This hash maps commonly-used limit types from
|
78
|
+
# the SENSORS_SUBFEATURE_* constants.
|
79
|
+
#
|
80
|
+
# I have not included ALL the subfeatures types,
|
81
|
+
# because there are around 100 of them, and most of
|
82
|
+
# them provide no post-processing value. I have, however,
|
83
|
+
# included the following subfeature groups for
|
84
|
+
# the _POWER_, _IN_, _CURR_, and _FAN_ categories:
|
85
|
+
#
|
86
|
+
# MIN, MAX, a couple HYST (hysteresis) types, INPUT,
|
87
|
+
# and a couple AVERAGE types.
|
88
|
+
#
|
89
|
+
# NOTE: For the MOST part, the below list is provided
|
90
|
+
# for convenience, only. You can use it to create your
|
91
|
+
# own mappers, if you are not sure what subtypes are
|
92
|
+
# included in the normal feature objects.
|
93
|
+
#
|
94
|
+
# I had actually considered removing everything below,
|
95
|
+
# but I realized that simply swapping the keys with the
|
96
|
+
# values actually provides a simpler way for others to
|
97
|
+
# access the types and provide some default key types
|
98
|
+
# they might want to use in their subclasses, even if it's
|
99
|
+
# somewhat redundant.
|
100
|
+
SSF_SUBTYPES = {
|
101
|
+
# Voltages
|
102
|
+
SF_IN => {
|
103
|
+
# Inputs
|
104
|
+
SSF_IN_INPUT => :input,
|
105
|
+
|
106
|
+
# Edge readings
|
107
|
+
SSF_IN_LOW => :lowest,
|
108
|
+
SSF_IN_HIGH => :highest,
|
109
|
+
|
110
|
+
# Minima and maxima
|
111
|
+
SSF_IN_MIN => :min,
|
112
|
+
SSF_IN_MAX => :max,
|
113
|
+
|
114
|
+
# Critical levels
|
115
|
+
SSF_IN_LCRIT => :lcrit,
|
116
|
+
SSF_IN_CRIT => :crit,
|
117
|
+
|
118
|
+
# Averages
|
119
|
+
SSF_IN_AVG => :average,
|
120
|
+
},
|
121
|
+
# Currents
|
122
|
+
SF_CURR => {
|
123
|
+
# Inputs
|
124
|
+
SSF_CURR_INPUT => :input,
|
125
|
+
|
126
|
+
# Edge readings
|
127
|
+
SSF_CURR_LOW => :lowest,
|
128
|
+
SSF_CURR_HIGH => :highest,
|
129
|
+
|
130
|
+
# Minima and maxima
|
131
|
+
SSF_CURR_MIN => :min,
|
132
|
+
SSF_CURR_MAX => :max,
|
133
|
+
|
134
|
+
# Critical levels
|
135
|
+
SSF_CURR_LCRIT => :lcrit,
|
136
|
+
SSF_CURR_CRIT => :crit,
|
137
|
+
|
138
|
+
# Averages
|
139
|
+
SSF_CURR_AVG => :average,
|
140
|
+
},
|
141
|
+
# Power
|
142
|
+
SF_POWER => {
|
143
|
+
# Inputs
|
144
|
+
SSF_POWER_INPUT => :input,
|
145
|
+
SSF_POWER_INPUT_LOW => :input_low,
|
146
|
+
SSF_POWER_INPUT_HIGH => :input_high,
|
147
|
+
|
148
|
+
# Minima and maxima
|
149
|
+
SSF_POWER_MIN => :min,
|
150
|
+
SSF_POWER_MAX => :max,
|
151
|
+
|
152
|
+
# Critical levels
|
153
|
+
SSF_POWER_LCRIT => :lcrit,
|
154
|
+
SSF_POWER_CRIT => :crit,
|
155
|
+
|
156
|
+
# Averages
|
157
|
+
SSF_POWER_AVG => :average,
|
158
|
+
SSF_POWER_AVG_LOW => :average_low,
|
159
|
+
SSF_POWER_AVG_HIGH => :average_high,
|
160
|
+
|
161
|
+
# Caps
|
162
|
+
SSF_POWER_CAP => :cap,
|
163
|
+
SSF_POWER_CAP_HYST => :cap_hyst,
|
164
|
+
},
|
165
|
+
|
166
|
+
# Temperatures
|
167
|
+
SF_TEMP => {
|
168
|
+
# Inputs
|
169
|
+
SSF_TEMP_INPUT => :input,
|
170
|
+
|
171
|
+
# Edge readings
|
172
|
+
SSF_TEMP_LOW => :lowest,
|
173
|
+
SSF_TEMP_HIGH => :highest,
|
174
|
+
|
175
|
+
# Minima and maxima + hysteresis
|
176
|
+
SSF_TEMP_MIN => :min,
|
177
|
+
SSF_TEMP_MIN_HYST => :min_hyst,
|
178
|
+
SSF_TEMP_MAX => :max,
|
179
|
+
SSF_TEMP_MAX_HYST => :max_hyst,
|
180
|
+
|
181
|
+
# Critical and emergency levels + hysteresis
|
182
|
+
SSF_TEMP_LCRIT => :lcrit,
|
183
|
+
SSF_TEMP_LCRIT_HYST => :lcrit_hyst,
|
184
|
+
SSF_TEMP_CRIT => :crit,
|
185
|
+
SSF_TEMP_CRIT_HYST => :crit_hyst,
|
186
|
+
SSF_TEMP_EMERG => :emergency,
|
187
|
+
SSF_TEMP_EMERG_HYST => :emergency_hyst,
|
188
|
+
},
|
189
|
+
# Fans
|
190
|
+
# Fan sensors have a simple structure that is self-explanatory.
|
191
|
+
SF_FAN => { SSF_FAN_INPUT => :input, SSF_FAN_MIN => :min, SSF_FAN_MAX => :max, },
|
192
|
+
} # End SSF subtypes
|
193
|
+
end # End LmSensors constants maps
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# lib/lmsensors/lmsensors.rb
|
2
|
+
|
3
|
+
# Base requires
|
4
|
+
require_relative "../lmsensors_base/lmsensors_base"
|
5
|
+
require_relative "./lm_constants"
|
6
|
+
|
7
|
+
require_relative "./sensors/sensorspawner"
|
8
|
+
require_relative "./sensors/sensor"
|
9
|
+
|
10
|
+
require_relative "./feature"
|
11
|
+
|
12
|
+
##
|
13
|
+
# LmSensors is the wrapping module for the entire
|
14
|
+
# lm-sensors library. This module provides the ability
|
15
|
+
# to initialize for and clean up resources from it, to
|
16
|
+
# generate Sensor objects that can be used to monitor
|
17
|
+
# specific pieces of hardware, as desired, and to generate
|
18
|
+
# a SensorSpawner to enumerate what sensors are available.
|
19
|
+
module LmSensors
|
20
|
+
##
|
21
|
+
# Wraps the 'pro_init' function to initialize the sensors
|
22
|
+
def self.init(filename=nil) self.pro_init(filename) end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Wraps the 'pro_cleanup' function to release the resources
|
26
|
+
def self.cleanup() self.pro_cleanup end
|
27
|
+
|
28
|
+
##
|
29
|
+
# For compatibility purposes, as this was
|
30
|
+
# being tested by some people, Sensors is now
|
31
|
+
# purely an alias of SensorSpawner.
|
32
|
+
Sensors = LmSensors::SensorSpawner
|
33
|
+
end # End LmSensors module
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# lib/lmsensors/sensors/abssensors.rb
|
2
|
+
|
3
|
+
# Requires
|
4
|
+
require_relative "../../lmsensors_base/lmsensors_base"
|
5
|
+
require_relative "../lm_constants"
|
6
|
+
require_relative "../feature"
|
7
|
+
|
8
|
+
# :nodoc: This module will house the abstract implementation
|
9
|
+
# :nodoc: of a general sensor-type object.
|
10
|
+
module LmSensors
|
11
|
+
##
|
12
|
+
# AbsSensor is an abstract representation of
|
13
|
+
# a sensor-type object and provides a base interface
|
14
|
+
# for required functions (operates like a trait).
|
15
|
+
class AbsSensor < LmSensors::SensorsBase
|
16
|
+
##
|
17
|
+
# AbsSensor :chip_name is the name sensors returns for the chip
|
18
|
+
attr_reader :chip_name
|
19
|
+
##
|
20
|
+
# AbsSensor :filters are the selected feature types to return for your use case
|
21
|
+
attr_reader :filters
|
22
|
+
##
|
23
|
+
# AbsSensor :fmap is a custom formatter map or the default DEF_FMAP
|
24
|
+
attr_reader :fmap
|
25
|
+
##
|
26
|
+
# AbsSensor :fmt is a boolean of whether or not to return the data formatted
|
27
|
+
attr_reader :fmt
|
28
|
+
##
|
29
|
+
# AbsSensor :subs is whether to return the subfeatures or just the feature
|
30
|
+
# and its type
|
31
|
+
attr_reader :subs
|
32
|
+
|
33
|
+
##
|
34
|
+
# Constructor
|
35
|
+
def initialize
|
36
|
+
pro_initialize
|
37
|
+
unset_filters
|
38
|
+
@fmt = @subs = false
|
39
|
+
@fmap = LmSensors::DEF_FMAP
|
40
|
+
end # End constructor
|
41
|
+
|
42
|
+
##
|
43
|
+
# Get the chip_name
|
44
|
+
def name() @chip_name end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Set the sensor's filters, the types that
|
48
|
+
# will be returned on '.features'.
|
49
|
+
def set_filters(arr)
|
50
|
+
if Array === arr then
|
51
|
+
@filters = arr.select { |item| LmSensors::UNITS.include? item } .sort
|
52
|
+
else STDERR.puts "::Sensors ERROR:: Filters must be an array" end
|
53
|
+
end # End set filters
|
54
|
+
|
55
|
+
##
|
56
|
+
# Unset the filters for this sensor
|
57
|
+
def unset_filters() @filters = [] end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Toggle whether this sensor also returns
|
61
|
+
# subfeatures on a feature list request.
|
62
|
+
def toggle_subs() @subs = !@subs end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Toggle if the sensor will report with
|
66
|
+
# formatted output or unformatted. Default
|
67
|
+
# is to report unformatted.
|
68
|
+
def toggle_fmt() @fmt = !@fmt end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Set the format mapper for the different types.
|
72
|
+
# This method should receive a proc that maps to different
|
73
|
+
# feature formatters.
|
74
|
+
def set_fmap(map)
|
75
|
+
# Only accept a proc/lambda for format mapping
|
76
|
+
if Proc === map then
|
77
|
+
if map.arity != 2 then
|
78
|
+
if !$LmSensorsIgnArity then
|
79
|
+
STDERR.puts <<~EMSG
|
80
|
+
::SensorSpawner WARNING:: @fmap arity should be 2 and will
|
81
|
+
NOT WORK without being overridden in a custom subclass.
|
82
|
+
|
83
|
+
If you are receiving this message, and you have already
|
84
|
+
overridden the subclasses and format handling, you should
|
85
|
+
set the global variable $LmSensorsIgnArity to 'true'.
|
86
|
+
|
87
|
+
This is only a warning and will not stop the map from
|
88
|
+
being set, even if it is invalid.
|
89
|
+
|
90
|
+
This warning will NOT be displayed again in this run.
|
91
|
+
EMSG
|
92
|
+
$LmSensorsIgnArity = true
|
93
|
+
end
|
94
|
+
@fmap = map
|
95
|
+
end
|
96
|
+
else # If it's not a proc, spit out an error
|
97
|
+
STDERR.puts "::Sensors ERROR:: Format map must be a proc/lambda"
|
98
|
+
end
|
99
|
+
end # End format mapper
|
100
|
+
|
101
|
+
##
|
102
|
+
# Reset the formatting map
|
103
|
+
def reset_fmap() @fmap = LmSensors::DEF_FMAP end
|
104
|
+
|
105
|
+
##
|
106
|
+
# Abstract enum must be implemented
|
107
|
+
# by subclasses
|
108
|
+
def enum(*args)
|
109
|
+
STDERR.puts "::AbsSensor ERROR:: Abstract 'enum' not implemented for #{self.class}"
|
110
|
+
[]
|
111
|
+
end # End abstract enum
|
112
|
+
|
113
|
+
##
|
114
|
+
# Get the number of sensors available
|
115
|
+
# for the current name (or the total number
|
116
|
+
# of sensors available).
|
117
|
+
def count
|
118
|
+
data = enum
|
119
|
+
if ([Hash, Array].include?(data.class)) then
|
120
|
+
# If the data is good
|
121
|
+
data.count
|
122
|
+
else return nil end
|
123
|
+
|
124
|
+
end # End count of sensors
|
125
|
+
alias :count_s :count # Add alias for backwards compatibility
|
126
|
+
|
127
|
+
# Protected methods
|
128
|
+
protected
|
129
|
+
|
130
|
+
##
|
131
|
+
# Validate a path -- protected
|
132
|
+
def path_valid?(path)
|
133
|
+
# Check that the path argument is a string
|
134
|
+
if (!path.is_a?(String)) then
|
135
|
+
STDERR.puts "::Sensor ERROR:: Path must be string!"
|
136
|
+
return nil
|
137
|
+
end # End check for correct path
|
138
|
+
# Clean the path input
|
139
|
+
dir = path.strip.gsub(/\/*$/, "")
|
140
|
+
|
141
|
+
# Check if path is a directory, else exit early.
|
142
|
+
# Do not need to check File.exist? first, b/c this
|
143
|
+
# already returns nil, if it doesn't.
|
144
|
+
if !File.directory?(dir) then
|
145
|
+
STDERR.puts "::Sensors ERROR:: Path is either invalid or not a directory!"
|
146
|
+
return nil
|
147
|
+
end # End directory check
|
148
|
+
dir # Return the correct path
|
149
|
+
end # End path validation
|
150
|
+
end # End Sensors class
|
151
|
+
end # End LmSensors append
|
@@ -0,0 +1,148 @@
|
|
1
|
+
# lib/lmsensors/sensors/sensors.rb
|
2
|
+
|
3
|
+
# Require the abstract sensor
|
4
|
+
require_relative "./abssensor"
|
5
|
+
|
6
|
+
# :nodoc: This module will house the concrete implementation
|
7
|
+
# :nodoc: of the actual Sensor object types.
|
8
|
+
module LmSensors
|
9
|
+
##
|
10
|
+
# Sensor is a concrete implementation
|
11
|
+
# of the AbsSensor. This implementation
|
12
|
+
# is a specific object dedicated to an
|
13
|
+
# individual sensor chip.
|
14
|
+
class Sensor < LmSensors::AbsSensor
|
15
|
+
##
|
16
|
+
# Sensor :path is the '/sys/class/hwmon/' path for this specific sensor
|
17
|
+
attr_reader :path
|
18
|
+
# Sensor :adapter is the adapter type, like the PCI or ISA adapter
|
19
|
+
attr_reader :adapter
|
20
|
+
|
21
|
+
##
|
22
|
+
# Find a device sensors by its path, in such
|
23
|
+
# a case where the app already has a device from
|
24
|
+
# sysfs or similar and needs to attach them together.
|
25
|
+
#
|
26
|
+
# Sets the name of the sensor, as well, so this should
|
27
|
+
# be used as an instance.
|
28
|
+
def locate(path)
|
29
|
+
# Validate the path
|
30
|
+
dir = path_valid?(path)
|
31
|
+
if !dir then return nil end
|
32
|
+
# Determine if it's a valid sensor, since the
|
33
|
+
# sensors here use the path as the index.
|
34
|
+
# If so, set it as this object's name
|
35
|
+
raw = pro_enum(nil, nil)
|
36
|
+
# Check if the enum value is valid
|
37
|
+
if (![Hash, Array].include?(raw.class)) then
|
38
|
+
STDERR.puts raw
|
39
|
+
return nil
|
40
|
+
end # End enum check
|
41
|
+
raw.then do |sensors|
|
42
|
+
# Return early, if it's not in the keys
|
43
|
+
if !sensors.keys.include?(dir) then
|
44
|
+
STDERR.puts "Path does not have an associated sensor"
|
45
|
+
return nil
|
46
|
+
end # End check for valid sensor path
|
47
|
+
|
48
|
+
# Set the data and return the chip name
|
49
|
+
data = sensors[dir]
|
50
|
+
@chip_name = data[:name]
|
51
|
+
@adapter = data[:adapter]
|
52
|
+
@path = data[:path]
|
53
|
+
@chip_name
|
54
|
+
end # End enumeration handler
|
55
|
+
end # End locate by path
|
56
|
+
|
57
|
+
##
|
58
|
+
# Return the core chip data. This does NOT include
|
59
|
+
# the features and subfeatures, just the information
|
60
|
+
# on the chip itself.
|
61
|
+
def info() { name: name, adapter: @adapter, path: @path, } end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Stat will return the values and names
|
65
|
+
# of all the features associated with the
|
66
|
+
# currently-selected chip. This has replaced
|
67
|
+
# :features, which is now just an alias for :stat.
|
68
|
+
#
|
69
|
+
# 2021-May-31 (pre-release): Now respects @filters
|
70
|
+
def stat
|
71
|
+
# For each chip, split it by key and value
|
72
|
+
raw = read
|
73
|
+
# Check that the data is still valid
|
74
|
+
if raw.nil? then return nil end
|
75
|
+
data = raw.collect do |feature, keys|
|
76
|
+
# Is the filter set?
|
77
|
+
no_filter = @filters.empty?
|
78
|
+
# Is the feature of a type included in the filter?
|
79
|
+
included = @filters.include?(keys[:type])
|
80
|
+
|
81
|
+
# If the filter is NOT set, OR the keys IS included
|
82
|
+
# in the filter, proceed.
|
83
|
+
if no_filter or included then
|
84
|
+
# If the subfeature option is set, return
|
85
|
+
# the subfeature data and the unit.
|
86
|
+
if @subs then
|
87
|
+
@fmap.call(feature, keys)
|
88
|
+
# If the subfeature option is not set, just return
|
89
|
+
# the feature type.
|
90
|
+
else { feature => keys[:type] } end
|
91
|
+
# If filtered and not included, return empty array
|
92
|
+
else [] end
|
93
|
+
end.flatten # Remove any empty units
|
94
|
+
# If format is set, format the output
|
95
|
+
if (@fmt and @subs) then data.collect { |item| item.fmt } else data end
|
96
|
+
end
|
97
|
+
# Pseudo-alias abstract enum to stat, for this class
|
98
|
+
def enum(*args) stat end
|
99
|
+
|
100
|
+
##
|
101
|
+
# :features is now an alias for :stat,
|
102
|
+
# as :stat did not previously respect @filters
|
103
|
+
alias :features :stat
|
104
|
+
|
105
|
+
##
|
106
|
+
# Get the number of features available for
|
107
|
+
# the current name (or total features to be
|
108
|
+
# read for all sensors). This overrides the
|
109
|
+
# abstract ``.count`` method.
|
110
|
+
def count
|
111
|
+
data = read
|
112
|
+
if !data then return nil end
|
113
|
+
# If the data is good
|
114
|
+
data.count
|
115
|
+
end # End count method
|
116
|
+
|
117
|
+
##
|
118
|
+
# Get the number of subfeatures available for
|
119
|
+
# the current name (or total features to be
|
120
|
+
# read for all sensors).
|
121
|
+
def count_sf
|
122
|
+
total = 0 # Accumulator
|
123
|
+
data = read
|
124
|
+
if !data then return nil end
|
125
|
+
# If the data is good, continue
|
126
|
+
data.each do |_, v|
|
127
|
+
# Ignore the :type symbol
|
128
|
+
total += (v.select { |item| :type != item } .count)
|
129
|
+
end
|
130
|
+
total # Return accumulator
|
131
|
+
end # End count of subfeatures
|
132
|
+
|
133
|
+
##
|
134
|
+
# Raw chip data -- this is unfiltered and unformatted.
|
135
|
+
#
|
136
|
+
# This has replaced the previous version of :stat, as
|
137
|
+
# :stat unintentionally did not respect the @filters.
|
138
|
+
def read
|
139
|
+
c = pro_enum(true, @chip_name)
|
140
|
+
if Hash === c then
|
141
|
+
c[@path][:stat]
|
142
|
+
else
|
143
|
+
STDERR.puts c
|
144
|
+
return nil
|
145
|
+
end
|
146
|
+
end # End read
|
147
|
+
end # End Sensor class
|
148
|
+
end # End LmSensors append
|