blob: 19a23094e94a3ccee7312080c8bbe742016fdc31 [file] [log] [blame]
Norman James323ed972015-12-09 09:06:37 -06001#!/usr/bin/python -u
2
3import sys
4import os
5import gobject
Norman James3bb97d92015-12-18 14:57:22 -06006import glob
Norman James323ed972015-12-09 09:06:37 -06007import dbus
8import dbus.service
9import dbus.mainloop.glib
10import Openbmc
Norman James3bb97d92015-12-18 14:57:22 -060011import re
12
Norman James323ed972015-12-09 09:06:37 -060013from Sensors import SensorValue as SensorValue
14from Sensors import HwmonSensor as HwmonSensor
15from Sensors import SensorThresholds as SensorThresholds
Norman James3bb97d92015-12-18 14:57:22 -060016
Norman James323ed972015-12-09 09:06:37 -060017if (len(sys.argv) < 2):
18 print "Usage: sensors_hwmon.py [system name]"
19 exit(1)
20
21System = __import__(sys.argv[1])
22
23SENSOR_BUS = 'org.openbmc.Sensors'
24SENSOR_PATH = '/org/openbmc/sensors'
Norman James3bb97d92015-12-18 14:57:22 -060025DIR_POLL_INTERVAL = 30000
Norman James323ed972015-12-09 09:06:37 -060026HWMON_PATH = '/sys/class/hwmon'
27
28## static define which interface each property is under
29## need a better way that is not slow
30IFACE_LOOKUP = {
31 'units' : SensorValue.IFACE_NAME,
32 'scale' : HwmonSensor.IFACE_NAME,
33 'offset' : HwmonSensor.IFACE_NAME,
34 'critical_upper' : SensorThresholds.IFACE_NAME,
35 'warning_upper' : SensorThresholds.IFACE_NAME,
36 'critical_lower' : SensorThresholds.IFACE_NAME,
37 'warning_lower' : SensorThresholds.IFACE_NAME,
Norman James72567ba2016-01-13 16:57:48 -060038 'emergency_enabled' : SensorThresholds.IFACE_NAME,
Norman James323ed972015-12-09 09:06:37 -060039}
40
41class Hwmons():
42 def __init__(self,bus):
43 self.sensors = { }
44 self.hwmon_root = { }
45 self.scanDirectory()
46 gobject.timeout_add(DIR_POLL_INTERVAL, self.scanDirectory)
Brad Bishopefc68972016-06-05 17:56:20 -040047 self.cache = {}
Norman James323ed972015-12-09 09:06:37 -060048
49 def readAttribute(self,filename):
Ken6956bbd2016-06-08 14:50:59 +080050 val = "-1"
51 try:
Norman James323ed972015-12-09 09:06:37 -060052 with open(filename, 'r') as f:
53 for line in f:
54 val = line.rstrip('\n')
Ken6956bbd2016-06-08 14:50:59 +080055 except (OSError, IOError):
56 print "Cannot read attributes:", filename
Norman James323ed972015-12-09 09:06:37 -060057 return val
58
59 def writeAttribute(self,filename,value):
60 with open(filename, 'w') as f:
61 f.write(str(value)+'\n')
62
Brad Bishopefc68972016-06-05 17:56:20 -040063 def should_update(attribute, value):
64 if attribute not in self.cache:
65 self.cache[attribute] = value
66 return True
67
68 update = (value != self.cache[attribute])
69 self.cache[attribute] = value
70
71 return update
Norman James323ed972015-12-09 09:06:37 -060072
73 def poll(self,objpath,attribute):
74 try:
75 raw_value = int(self.readAttribute(attribute))
Brad Bishopefc68972016-06-05 17:56:20 -040076 if self.should_update(attribute, raw_value):
77 obj = bus.get_object(SENSOR_BUS,objpath,introspect=False)
78 intf = dbus.Interface(obj,HwmonSensor.IFACE_NAME)
79 rtn = intf.setByPoll(raw_value)
80 if (rtn[0] == True):
81 self.writeAttribute(attribute,rtn[1])
Norman James323ed972015-12-09 09:06:37 -060082 except:
83 print "HWMON: Attibute no longer exists: "+attribute
Ken6956bbd2016-06-08 14:50:59 +080084 self.sensors.pop(objpath,None)
Brad Bishopefc68972016-06-05 17:56:20 -040085 if attribute in self.cache:
86 del self.cache[attribute]
Norman James323ed972015-12-09 09:06:37 -060087 return False
88
89
90 return True
91
92
Norman James3bb97d92015-12-18 14:57:22 -060093 def addObject(self,dpath,hwmon_path,hwmon):
Norman James323ed972015-12-09 09:06:37 -060094 objsuf = hwmon['object_path']
Norman James323ed972015-12-09 09:06:37 -060095 objpath = SENSOR_PATH+'/'+objsuf
Norman James3bb97d92015-12-18 14:57:22 -060096
Norman James323ed972015-12-09 09:06:37 -060097 if (self.sensors.has_key(objpath) == False):
Norman James3bb97d92015-12-18 14:57:22 -060098 print "HWMON add: "+objpath+" : "+hwmon_path
99
100 ## register object with sensor manager
101 obj = bus.get_object(SENSOR_BUS,SENSOR_PATH,introspect=False)
102 intf = dbus.Interface(obj,SENSOR_BUS)
103 intf.register("HwmonSensor",objpath)
104
105 ## set some properties in dbus object
106 obj = bus.get_object(SENSOR_BUS,objpath,introspect=False)
107 intf = dbus.Interface(obj,dbus.PROPERTIES_IFACE)
108 intf.Set(HwmonSensor.IFACE_NAME,'filename',hwmon_path)
Norman James323ed972015-12-09 09:06:37 -0600109
Norman James3bb97d92015-12-18 14:57:22 -0600110 ## check if one of thresholds is defined to know
111 ## whether to enable thresholds or not
112 if (hwmon.has_key('critical_upper')):
113 intf.Set(SensorThresholds.IFACE_NAME,'thresholds_enabled',True)
Norman James323ed972015-12-09 09:06:37 -0600114
Norman James3bb97d92015-12-18 14:57:22 -0600115 for prop in hwmon.keys():
116 if (IFACE_LOOKUP.has_key(prop)):
117 intf.Set(IFACE_LOOKUP[prop],prop,hwmon[prop])
118 print "Setting: "+prop+" = "+str(hwmon[prop])
Norman James323ed972015-12-09 09:06:37 -0600119
Norman James3bb97d92015-12-18 14:57:22 -0600120 self.sensors[objpath]=True
121 self.hwmon_root[dpath].append(objpath)
122 gobject.timeout_add(hwmon['poll_interval'],self.poll,objpath,hwmon_path)
Norman James323ed972015-12-09 09:06:37 -0600123
124 def scanDirectory(self):
125 devices = os.listdir(HWMON_PATH)
126 found_hwmon = {}
Norman James3bb97d92015-12-18 14:57:22 -0600127 regx = re.compile('([a-z]+)\d+\_')
Norman James323ed972015-12-09 09:06:37 -0600128 for d in devices:
129 dpath = HWMON_PATH+'/'+d+'/'
130 found_hwmon[dpath] = True
131 if (self.hwmon_root.has_key(dpath) == False):
132 self.hwmon_root[dpath] = []
133 ## the instance name is a soft link
134 instance_name = os.path.realpath(dpath+'device').split('/').pop()
Norman James3bb97d92015-12-18 14:57:22 -0600135
136
Norman James323ed972015-12-09 09:06:37 -0600137 if (System.HWMON_CONFIG.has_key(instance_name)):
Norman James3bb97d92015-12-18 14:57:22 -0600138 hwmon = System.HWMON_CONFIG[instance_name]
139
140 if (hwmon.has_key('labels')):
141 label_files = glob.glob(dpath+'/*_label')
142 for f in label_files:
143 label_key = self.readAttribute(f)
144 if (hwmon['labels'].has_key(label_key)):
145 namef = f.replace('_label','_input')
146 self.addObject(dpath,namef,hwmon['labels'][label_key])
147 else:
148 pass
149 #print "WARNING - hwmon: label ("+label_key+") not found in lookup: "+f
150
151 if hwmon.has_key('names'):
152 for attribute in hwmon['names'].keys():
153 self.addObject(dpath,dpath+attribute,hwmon['names'][attribute])
154
Norman James323ed972015-12-09 09:06:37 -0600155 else:
Norman James3bb97d92015-12-18 14:57:22 -0600156 print "WARNING - hwmon: Unhandled hwmon: "+dpath
Norman James323ed972015-12-09 09:06:37 -0600157
158
159 for k in self.hwmon_root.keys():
160 if (found_hwmon.has_key(k) == False):
161 ## need to remove all objects associated with this path
162 print "Removing: "+k
163 for objpath in self.hwmon_root[k]:
164 if (self.sensors.has_key(objpath) == True):
165 print "HWMON remove: "+objpath
166 self.sensors.pop(objpath,None)
Norman James3bb97d92015-12-18 14:57:22 -0600167 obj = bus.get_object(SENSOR_BUS,SENSOR_PATH,introspect=False)
Norman James323ed972015-12-09 09:06:37 -0600168 intf = dbus.Interface(obj,SENSOR_BUS)
169 intf.delete(objpath)
170
171 self.hwmon_root.pop(k,None)
172
173 return True
174
175
176if __name__ == '__main__':
177
178 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
179 bus = Openbmc.getDBus()
180 root_sensor = Hwmons(bus)
181 mainloop = gobject.MainLoop()
182
183 print "Starting HWMON sensors"
184 mainloop.run()
185