lmsensors 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|