blob: a91b761d77abcc8e5a0f44696be524e66e93e40a [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
Norman James3bb97d92015-12-18 14:57:22 -060010import re
Brad Bishop84e73b52016-05-12 15:57:52 -040011from obmc.dbuslib.bindings import get_dbus
Norman James3bb97d92015-12-18 14:57:22 -060012
Brad Bishopee1b1542016-05-12 16:55:00 -040013from obmc.sensors import SensorValue as SensorValue
14from obmc.sensors import HwmonSensor as HwmonSensor
15from obmc.sensors import SensorThresholds as SensorThresholds
Brad Bishop0b380f72016-06-10 00:29:50 -040016import obmc_system_config as System
Norman James323ed972015-12-09 09:06:37 -060017
18SENSOR_BUS = 'org.openbmc.Sensors'
19SENSOR_PATH = '/org/openbmc/sensors'
Norman James3bb97d92015-12-18 14:57:22 -060020DIR_POLL_INTERVAL = 30000
Norman James323ed972015-12-09 09:06:37 -060021HWMON_PATH = '/sys/class/hwmon'
22
23## static define which interface each property is under
24## need a better way that is not slow
25IFACE_LOOKUP = {
26 'units' : SensorValue.IFACE_NAME,
27 'scale' : HwmonSensor.IFACE_NAME,
28 'offset' : HwmonSensor.IFACE_NAME,
29 'critical_upper' : SensorThresholds.IFACE_NAME,
30 'warning_upper' : SensorThresholds.IFACE_NAME,
31 'critical_lower' : SensorThresholds.IFACE_NAME,
32 'warning_lower' : SensorThresholds.IFACE_NAME,
Norman James72567ba2016-01-13 16:57:48 -060033 'emergency_enabled' : SensorThresholds.IFACE_NAME,
Norman James323ed972015-12-09 09:06:37 -060034}
35
36class Hwmons():
37 def __init__(self,bus):
38 self.sensors = { }
39 self.hwmon_root = { }
40 self.scanDirectory()
41 gobject.timeout_add(DIR_POLL_INTERVAL, self.scanDirectory)
Brad Bishopefc68972016-06-05 17:56:20 -040042 self.cache = {}
Norman James323ed972015-12-09 09:06:37 -060043
44 def readAttribute(self,filename):
Ken6956bbd2016-06-08 14:50:59 +080045 val = "-1"
46 try:
Norman James323ed972015-12-09 09:06:37 -060047 with open(filename, 'r') as f:
48 for line in f:
49 val = line.rstrip('\n')
Ken6956bbd2016-06-08 14:50:59 +080050 except (OSError, IOError):
51 print "Cannot read attributes:", filename
Norman James323ed972015-12-09 09:06:37 -060052 return val
53
54 def writeAttribute(self,filename,value):
55 with open(filename, 'w') as f:
56 f.write(str(value)+'\n')
57
Brad Bishopefc68972016-06-05 17:56:20 -040058 def should_update(attribute, value):
59 if attribute not in self.cache:
60 self.cache[attribute] = value
61 return True
62
63 update = (value != self.cache[attribute])
64 self.cache[attribute] = value
65
66 return update
Norman James323ed972015-12-09 09:06:37 -060067
68 def poll(self,objpath,attribute):
69 try:
70 raw_value = int(self.readAttribute(attribute))
Brad Bishopefc68972016-06-05 17:56:20 -040071 if self.should_update(attribute, raw_value):
72 obj = bus.get_object(SENSOR_BUS,objpath,introspect=False)
73 intf = dbus.Interface(obj,HwmonSensor.IFACE_NAME)
74 rtn = intf.setByPoll(raw_value)
75 if (rtn[0] == True):
76 self.writeAttribute(attribute,rtn[1])
Norman James323ed972015-12-09 09:06:37 -060077 except:
78 print "HWMON: Attibute no longer exists: "+attribute
Ken6956bbd2016-06-08 14:50:59 +080079 self.sensors.pop(objpath,None)
Brad Bishopefc68972016-06-05 17:56:20 -040080 if attribute in self.cache:
81 del self.cache[attribute]
Norman James323ed972015-12-09 09:06:37 -060082 return False
83
84
85 return True
86
87
Norman James3bb97d92015-12-18 14:57:22 -060088 def addObject(self,dpath,hwmon_path,hwmon):
Norman James323ed972015-12-09 09:06:37 -060089 objsuf = hwmon['object_path']
Norman James323ed972015-12-09 09:06:37 -060090 objpath = SENSOR_PATH+'/'+objsuf
Norman James3bb97d92015-12-18 14:57:22 -060091
Norman James323ed972015-12-09 09:06:37 -060092 if (self.sensors.has_key(objpath) == False):
Norman James3bb97d92015-12-18 14:57:22 -060093 print "HWMON add: "+objpath+" : "+hwmon_path
94
95 ## register object with sensor manager
96 obj = bus.get_object(SENSOR_BUS,SENSOR_PATH,introspect=False)
97 intf = dbus.Interface(obj,SENSOR_BUS)
98 intf.register("HwmonSensor",objpath)
99
100 ## set some properties in dbus object
101 obj = bus.get_object(SENSOR_BUS,objpath,introspect=False)
102 intf = dbus.Interface(obj,dbus.PROPERTIES_IFACE)
103 intf.Set(HwmonSensor.IFACE_NAME,'filename',hwmon_path)
Norman James323ed972015-12-09 09:06:37 -0600104
Norman James3bb97d92015-12-18 14:57:22 -0600105 ## check if one of thresholds is defined to know
106 ## whether to enable thresholds or not
107 if (hwmon.has_key('critical_upper')):
108 intf.Set(SensorThresholds.IFACE_NAME,'thresholds_enabled',True)
Norman James323ed972015-12-09 09:06:37 -0600109
Norman James3bb97d92015-12-18 14:57:22 -0600110 for prop in hwmon.keys():
111 if (IFACE_LOOKUP.has_key(prop)):
112 intf.Set(IFACE_LOOKUP[prop],prop,hwmon[prop])
113 print "Setting: "+prop+" = "+str(hwmon[prop])
Norman James323ed972015-12-09 09:06:37 -0600114
Norman James3bb97d92015-12-18 14:57:22 -0600115 self.sensors[objpath]=True
116 self.hwmon_root[dpath].append(objpath)
117 gobject.timeout_add(hwmon['poll_interval'],self.poll,objpath,hwmon_path)
Norman James323ed972015-12-09 09:06:37 -0600118
119 def scanDirectory(self):
120 devices = os.listdir(HWMON_PATH)
121 found_hwmon = {}
Norman James3bb97d92015-12-18 14:57:22 -0600122 regx = re.compile('([a-z]+)\d+\_')
Norman James323ed972015-12-09 09:06:37 -0600123 for d in devices:
124 dpath = HWMON_PATH+'/'+d+'/'
125 found_hwmon[dpath] = True
126 if (self.hwmon_root.has_key(dpath) == False):
127 self.hwmon_root[dpath] = []
128 ## the instance name is a soft link
129 instance_name = os.path.realpath(dpath+'device').split('/').pop()
Norman James3bb97d92015-12-18 14:57:22 -0600130
131
Norman James323ed972015-12-09 09:06:37 -0600132 if (System.HWMON_CONFIG.has_key(instance_name)):
Norman James3bb97d92015-12-18 14:57:22 -0600133 hwmon = System.HWMON_CONFIG[instance_name]
134
135 if (hwmon.has_key('labels')):
136 label_files = glob.glob(dpath+'/*_label')
137 for f in label_files:
138 label_key = self.readAttribute(f)
139 if (hwmon['labels'].has_key(label_key)):
140 namef = f.replace('_label','_input')
141 self.addObject(dpath,namef,hwmon['labels'][label_key])
142 else:
143 pass
144 #print "WARNING - hwmon: label ("+label_key+") not found in lookup: "+f
145
146 if hwmon.has_key('names'):
147 for attribute in hwmon['names'].keys():
148 self.addObject(dpath,dpath+attribute,hwmon['names'][attribute])
149
Norman James323ed972015-12-09 09:06:37 -0600150 else:
Norman James3bb97d92015-12-18 14:57:22 -0600151 print "WARNING - hwmon: Unhandled hwmon: "+dpath
Norman James323ed972015-12-09 09:06:37 -0600152
153
154 for k in self.hwmon_root.keys():
155 if (found_hwmon.has_key(k) == False):
156 ## need to remove all objects associated with this path
157 print "Removing: "+k
158 for objpath in self.hwmon_root[k]:
159 if (self.sensors.has_key(objpath) == True):
160 print "HWMON remove: "+objpath
161 self.sensors.pop(objpath,None)
Norman James3bb97d92015-12-18 14:57:22 -0600162 obj = bus.get_object(SENSOR_BUS,SENSOR_PATH,introspect=False)
Norman James323ed972015-12-09 09:06:37 -0600163 intf = dbus.Interface(obj,SENSOR_BUS)
164 intf.delete(objpath)
165
166 self.hwmon_root.pop(k,None)
167
168 return True
169
170
171if __name__ == '__main__':
172
173 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
Brad Bishop84e73b52016-05-12 15:57:52 -0400174 bus = get_dbus()
Norman James323ed972015-12-09 09:06:37 -0600175 root_sensor = Hwmons(bus)
176 mainloop = gobject.MainLoop()
177
178 print "Starting HWMON sensors"
179 mainloop.run()
180