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; roslib.load_manifest('diagnostic_common_diagnostics')
38 import rospy
39 import diagnostic_updater as DIAG
40 
41 import socket, string
42 import subprocess
43 import math
44 import re
45 import sys
46 from StringIO import StringIO
47 
48 class Sensor(object):
49  def __init__(self):
50  self.critical = None
51  self.min = None
52  self.max = None
53  self.input = None
54  self.name = None
55  self.type = None
56  self.high = None
57  self.alarm = None
58 
59  def getCrit(self):
60  return self.critical
61 
62  def getMin(self):
63  return self.min
64 
65  def getMax(self):
66  return self.max
67 
68  def getInput(self):
69  return self.input
70 
71  def getName(self):
72  return self.name
73 
74  def getType(self):
75  return self.type
76 
77  def getHigh(self):
78  return self.high
79 
80  def getAlarm(self):
81  return self.alarm
82 
83  def __str__(self):
84  lines = []
85  lines.append(str(self.name))
86  lines.append("\t" + "Type: " + str(self.type))
87  if self.input:
88  lines.append("\t" + "Input: " + str(self.input))
89  if self.min:
90  lines.append("\t" + "Min: " + str(self.min))
91  if self.max:
92  lines.append("\t" + "Max: " + str(self.max))
93  if self.high:
94  lines.append("\t" + "High: " + str(self.high))
95  if self.critical:
96  lines.append("\t" + "Crit: " + str(self.critical))
97  lines.append("\t" + "Alarm: " + str(self.alarm))
98  return "\n".join(lines)
99 
100 
102  sensor = Sensor()
103  line = line.lstrip()
104  [name, reading] = line.split(":")
105 
106  #hack for when the name is temp1
107  if name.find("temp") != -1:
108  return None
109  else:
110  [sensor.name, sensor.type] = name.rsplit(" ",1)
111 
112  if sensor.name == "Core":
113  sensor.name = name
114  sensor.type = "Temperature"
115  elif sensor.name.find("Physical id") != -1:
116  sensor.name = name
117  sensor.type = "Temperature"
118 
119  [reading, params] = reading.lstrip().split("(")
120 
121  sensor.alarm = False
122  if line.find("ALARM") != -1:
123  sensor.alarm = True
124 
125  if reading.find("\xc2\xb0C") == -1:
126  sensor.input = float(reading.split()[0])
127  else:
128  sensor.input = float(reading.split("\xc2\xb0C")[0])
129 
130  params = params.split(",")
131  for param in params:
132  m = re.search("[0-9]+.[0-9]*", param)
133  if param.find("min") != -1:
134  sensor.min = float(m.group(0))
135  elif param.find("max") != -1:
136  sensor.max = float(m.group(0))
137  elif param.find("high") != -1:
138  sensor.high = float(m.group(0))
139  elif param.find("crit") != -1:
140  sensor.critical = float(m.group(0))
141 
142  return sensor
143 
144 def _rads_to_rpm(rads):
145  return rads / (2 * math.pi) * 60
146 
147 def _rpm_to_rads(rpm):
148  return rpm * (2 * math.pi) / 60
149 
151  out = StringIO(output)
152 
153  sensorList = []
154  for line in out.readlines():
155  # Check for a colon
156  if line.find(":") != -1 and line.find("Adapter") == -1:
157  s = parse_sensor_line(line)
158  if s is not None:
159  sensorList.append(s)
160  return sensorList
161 
163  p = subprocess.Popen('sensors', stdout = subprocess.PIPE,
164  stderr = subprocess.PIPE, shell = True)
165  (o,e) = p.communicate()
166  if not p.returncode == 0:
167  return ''
168  if not o:
169  return ''
170  return o
171 
172 class SensorsMonitor(object):
173  def __init__(self, hostname):
174  self.hostname = hostname
175  self.ignore_fans = rospy.get_param('~ignore_fans', False)
176  rospy.loginfo("Ignore fanspeed warnings: %s" % self.ignore_fans)
177 
178  self.updater = DIAG.Updater()
179  self.updater.setHardwareID("none")
180  self.updater.add('%s Sensor Status'%self.hostname, self.monitor)
181 
182  self.timer = rospy.Timer(rospy.Duration(1), self.timer_cb)
183 
184  def timer_cb(self, dummy):
185  self.updater.update()
186 
187  def monitor(self, stat):
188  try:
189  stat.summary(DIAG.OK, "OK")
190  for sensor in parse_sensors_output(get_sensors()):
191  if sensor.getType() == "Temperature":
192  if sensor.getInput() > sensor.getCrit():
193  stat.mergeSummary(DIAG.ERROR, "Critical Temperature")
194  elif sensor.getInput() > sensor.getHigh():
195  stat.mergeSummary(DIAG.WARN, "High Temperature")
196  stat.add(" ".join([sensor.getName(), sensor.getType()]), sensor.getInput())
197  elif sensor.getType() == "Voltage":
198  if sensor.getInput() < sensor.getMin():
199  stat.mergeSummary(DIAG.ERROR, "Low Voltage")
200  elif sensor.getInput() > sensor.getMax():
201  stat.mergeSummary(DIAG.ERROR, "High Voltage")
202  stat.add(" ".join([sensor.getName(), sensor.getType()]), sensor.getInput())
203  elif sensor.getType() == "Speed":
204  if not ignore_fans:
205  if sensor.getInput() < sensor.getMin():
206  stat.mergeSummary(DIAG.ERROR, "No Fan Speed")
207  stat.add(" ".join([sensor.getName(), sensor.getType()]), sensor.getInput())
208  except Exception, e:
209  import traceback
210  rospy.logerr('Unable to process lm-sensors data')
211  rospy.logerr(traceback.format_exc())
212  return stat
213 
214 if __name__ == '__main__':
215  hostname = socket.gethostname()
216  hostname_clean = string.translate(hostname, string.maketrans('-','_'))
217  try:
218  rospy.init_node('sensors_monitor_%s'%hostname_clean)
219  except rospy.ROSInitException:
220  print('Unable to initialize node. Master may not be running')
221  sys.exit(0)
222 
223  monitor = SensorsMonitor(hostname)
224  rospy.spin()


diagnostic_common_diagnostics
Author(s): Brice Rebsamen
autogenerated on Mon Feb 28 2022 22:18:19