sensors_monitor.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # Software License Agreement (BSD License)
4 #
5 # Copyright (c) 2012, Willow Garage, Inc.
6 # All rights reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions
10 # are met:
11 #
12 # * Redistributions of source code must retain the above copyright
13 # notice, this list of conditions and the following disclaimer.
14 # * Redistributions in binary form must reproduce the above
15 # copyright notice, this list of conditions and the following
16 # disclaimer in the documentation and/or other materials provided
17 # with the distribution.
18 # * Neither the name of the Willow Garage nor the names of its
19 # contributors may be used to endorse or promote products derived
20 # from this software without specific prior written permission.
21 #
22 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 # POSSIBILITY OF SUCH DAMAGE.
34 
35 from __future__ import with_statement, division
36 
37 import roslib
38 import rospy
39 import diagnostic_updater as DIAG
40 
41 import socket
42 import subprocess
43 import math
44 import re
45 import sys
46 from io import StringIO
47 roslib.load_manifest('diagnostic_common_diagnostics')
48 
49 
50 class Sensor(object):
51  def __init__(self):
52  self.critical = None
53  self.min = None
54  self.max = None
55  self.input = None
56  self.name = None
57  self.type = None
58  self.high = None
59  self.alarm = None
60 
61  def __repr__(self):
62  return 'Sensor object (name: {}, type: {})'.format(self.name,
63  self.type)
64 
65  def getCrit(self):
66  return self.critical
67 
68  def getMin(self):
69  return self.min
70 
71  def getMax(self):
72  return self.max
73 
74  def getInput(self):
75  return self.input
76 
77  def getName(self):
78  return self.name
79 
80  def getType(self):
81  return self.type
82 
83  def getHigh(self):
84  return self.high
85 
86  def getAlarm(self):
87  return self.alarm
88 
89  def __str__(self):
90  lines = []
91  lines.append(str(self.name))
92  lines.append("\t" + "Type: " + str(self.type))
93  if self.input:
94  lines.append("\t" + "Input: " + str(self.input))
95  if self.min:
96  lines.append("\t" + "Min: " + str(self.min))
97  if self.max:
98  lines.append("\t" + "Max: " + str(self.max))
99  if self.high:
100  lines.append("\t" + "High: " + str(self.high))
101  if self.critical:
102  lines.append("\t" + "Crit: " + str(self.critical))
103  lines.append("\t" + "Alarm: " + str(self.alarm))
104  return "\n".join(lines)
105 
106 
108  sensor = Sensor()
109  line = line.lstrip()
110  [name, reading] = line.split(":")
111 
112  try:
113  [sensor.name, sensor.type] = name.rsplit(" ", 1)
114  except ValueError:
115  return None
116 
117  if sensor.name == "Core":
118  sensor.name = name
119  sensor.type = "Temperature"
120  elif sensor.name.find("Physical id") != -1:
121  sensor.name = name
122  sensor.type = "Temperature"
123 
124  try:
125  [reading, params] = reading.lstrip().split("(")
126  except ValueError:
127  return None
128 
129  sensor.alarm = False
130  if line.find("ALARM") != -1:
131  sensor.alarm = True
132 
133  if reading.find("°C") == -1:
134  sensor.input = float(reading.split()[0])
135  else:
136  sensor.input = float(reading.split("°C")[0])
137 
138  params = params.split(",")
139  for param in params:
140  m = re.search("[0-9]+.[0-9]*", param)
141  if param.find("min") != -1:
142  sensor.min = float(m.group(0))
143  elif param.find("max") != -1:
144  sensor.max = float(m.group(0))
145  elif param.find("high") != -1:
146  sensor.high = float(m.group(0))
147  elif param.find("crit") != -1:
148  sensor.critical = float(m.group(0))
149 
150  return sensor
151 
152 
153 def _rads_to_rpm(rads):
154  return rads / (2 * math.pi) * 60
155 
156 
157 def _rpm_to_rads(rpm):
158  return rpm * (2 * math.pi) / 60
159 
160 
162  out = StringIO(output if isinstance(output, str) else output.decode('utf-8'))
163 
164  sensorList = []
165  for line in out.readlines():
166  # Check for a colon
167  if ":" in line and "Adapter" not in line:
168  try:
169  s = parse_sensor_line(line)
170  except Exception as exc:
171  rospy.logwarn('Unable to parse line "%s", due to %s', line, exc)
172  if s is not None:
173  sensorList.append(s)
174  return sensorList
175 
176 
178  p = subprocess.Popen('sensors', stdout=subprocess.PIPE,
179  stderr=subprocess.PIPE, shell=True)
180  (o, e) = p.communicate()
181  if not p.returncode == 0:
182  return ''
183  if not o:
184  return ''
185  return o
186 
187 
188 class SensorsMonitor(object):
189 
190  def __init__(self, hostname):
191  self.hostname = hostname
192  self.ignore_fans = rospy.get_param('~ignore_fans', False)
193  rospy.loginfo("Ignore fanspeed warnings: %s" % self.ignore_fans)
194 
195  self.updater = DIAG.Updater()
196  self.updater.setHardwareID("none")
197  self.updater.add('%s Sensor Status' % self.hostname, self.monitor)
198 
199  self.timer = rospy.Timer(rospy.Duration(1), self.timer_cb)
200 
201  def timer_cb(self, dummy):
202  self.updater.update()
203 
204  def monitor(self, stat):
205  try:
206  stat.summary(DIAG.OK, "OK")
207  for sensor in parse_sensors_output(get_sensors()):
208  if sensor.getType() == "Temperature":
209  if sensor.getInput() > sensor.getCrit():
210  stat.mergeSummary(DIAG.ERROR, "Critical Temperature")
211  elif sensor.getInput() > sensor.getHigh():
212  stat.mergeSummary(DIAG.WARN, "High Temperature")
213  stat.add(" ".join([sensor.getName(), sensor.getType()]), sensor.getInput())
214  elif sensor.getType() == "Voltage":
215  if sensor.getInput() < sensor.getMin():
216  stat.mergeSummary(DIAG.ERROR, "Low Voltage")
217  elif sensor.getInput() > sensor.getMax():
218  stat.mergeSummary(DIAG.ERROR, "High Voltage")
219  stat.add(" ".join([sensor.getName(), sensor.getType()]), sensor.getInput())
220  elif sensor.getType() == "Speed":
221  if not self.ignore_fans:
222  if sensor.getInput() < sensor.getMin():
223  stat.mergeSummary(DIAG.ERROR, "No Fan Speed")
224  stat.add(" ".join([sensor.getName(), sensor.getType()]), sensor.getInput())
225  except Exception:
226  import traceback
227  rospy.logerr('Unable to process lm-sensors data')
228  rospy.logerr(traceback.format_exc())
229  return stat
230 
231 
232 if __name__ == '__main__':
233  hostname = socket.gethostname()
234  hostname_clean = hostname.translate(hostname.maketrans('-', '_'))
235  try:
236  rospy.init_node('sensors_monitor_%s' % hostname_clean)
237  except rospy.ROSInitException:
238  print('Unable to initialize node. Master may not be running')
239  sys.exit(0)
240 
241  monitor = SensorsMonitor(hostname)
242  rospy.spin()
diagnostic_common_diagnostics.sensors_monitor.Sensor.getCrit
def getCrit(self)
Definition: sensors_monitor.py:65
diagnostic_common_diagnostics.sensors_monitor.Sensor.getInput
def getInput(self)
Definition: sensors_monitor.py:74
diagnostic_common_diagnostics.sensors_monitor.Sensor.getName
def getName(self)
Definition: sensors_monitor.py:77
diagnostic_common_diagnostics.sensors_monitor.SensorsMonitor
Definition: sensors_monitor.py:188
diagnostic_common_diagnostics.sensors_monitor.Sensor.getMin
def getMin(self)
Definition: sensors_monitor.py:68
diagnostic_common_diagnostics.sensors_monitor.Sensor.getHigh
def getHigh(self)
Definition: sensors_monitor.py:83
diagnostic_common_diagnostics.sensors_monitor.Sensor.min
min
Definition: sensors_monitor.py:53
diagnostic_common_diagnostics.sensors_monitor.SensorsMonitor.ignore_fans
ignore_fans
Definition: sensors_monitor.py:192
diagnostic_common_diagnostics.sensors_monitor.Sensor.__init__
def __init__(self)
Definition: sensors_monitor.py:51
diagnostic_common_diagnostics.sensors_monitor._rpm_to_rads
def _rpm_to_rads(rpm)
Definition: sensors_monitor.py:157
diagnostic_common_diagnostics.sensors_monitor.parse_sensors_output
def parse_sensors_output(output)
Definition: sensors_monitor.py:161
diagnostic_common_diagnostics.sensors_monitor.SensorsMonitor.monitor
def monitor(self, stat)
Definition: sensors_monitor.py:204
diagnostic_common_diagnostics.sensors_monitor.Sensor.getMax
def getMax(self)
Definition: sensors_monitor.py:71
diagnostic_common_diagnostics.sensors_monitor.Sensor.getAlarm
def getAlarm(self)
Definition: sensors_monitor.py:86
diagnostic_common_diagnostics.sensors_monitor.Sensor.__str__
def __str__(self)
Definition: sensors_monitor.py:89
diagnostic_common_diagnostics.sensors_monitor.Sensor.high
high
Definition: sensors_monitor.py:58
diagnostic_common_diagnostics.sensors_monitor.Sensor.type
type
Definition: sensors_monitor.py:57
diagnostic_common_diagnostics.sensors_monitor.SensorsMonitor.__init__
def __init__(self, hostname)
Definition: sensors_monitor.py:190
diagnostic_common_diagnostics.sensors_monitor.SensorsMonitor.timer_cb
def timer_cb(self, dummy)
Definition: sensors_monitor.py:201
diagnostic_common_diagnostics.sensors_monitor.Sensor.alarm
alarm
Definition: sensors_monitor.py:59
diagnostic_common_diagnostics.sensors_monitor.SensorsMonitor.updater
updater
Definition: sensors_monitor.py:195
diagnostic_common_diagnostics.sensors_monitor._rads_to_rpm
def _rads_to_rpm(rads)
Definition: sensors_monitor.py:153
diagnostic_common_diagnostics.sensors_monitor.Sensor.critical
critical
Definition: sensors_monitor.py:52
diagnostic_common_diagnostics.sensors_monitor.Sensor.getType
def getType(self)
Definition: sensors_monitor.py:80
diagnostic_common_diagnostics.sensors_monitor.Sensor.name
name
Definition: sensors_monitor.py:56
diagnostic_common_diagnostics.sensors_monitor.Sensor.max
max
Definition: sensors_monitor.py:54
diagnostic_common_diagnostics.sensors_monitor.Sensor
Definition: sensors_monitor.py:50
diagnostic_common_diagnostics.sensors_monitor.Sensor.__repr__
def __repr__(self)
Definition: sensors_monitor.py:61
diagnostic_common_diagnostics.sensors_monitor.Sensor.input
input
Definition: sensors_monitor.py:55
diagnostic_common_diagnostics.sensors_monitor.SensorsMonitor.hostname
hostname
Definition: sensors_monitor.py:191
diagnostic_common_diagnostics.sensors_monitor.SensorsMonitor.timer
timer
Definition: sensors_monitor.py:199
diagnostic_common_diagnostics.sensors_monitor.parse_sensor_line
def parse_sensor_line(line)
Definition: sensors_monitor.py:107
diagnostic_common_diagnostics.sensors_monitor.get_sensors
def get_sensors()
Definition: sensors_monitor.py:177


diagnostic_common_diagnostics
Author(s): Brice Rebsamen
autogenerated on Tue Nov 15 2022 03:17:21