blob: 0b6cf5f85f9b091b593fa63faaa342d0c225408f [file] [log] [blame]
Brad Bishop2fa78fb2016-08-30 19:51:51 -04001#!/usr/bin/env python
Norman James323ed972015-12-09 09:06:37 -06002
Norman James323ed972015-12-09 09:06:37 -06003import os
4import gobject
Norman James3bb97d92015-12-18 14:57:22 -06005import glob
Norman James323ed972015-12-09 09:06:37 -06006import dbus
7import dbus.service
8import dbus.mainloop.glib
Norman James3bb97d92015-12-18 14:57:22 -06009import re
Brad Bishop84e73b52016-05-12 15:57:52 -040010from obmc.dbuslib.bindings import get_dbus
Norman James3bb97d92015-12-18 14:57:22 -060011
Brad Bishopee1b1542016-05-12 16:55:00 -040012from obmc.sensors import SensorValue as SensorValue
13from obmc.sensors import HwmonSensor as HwmonSensor
14from obmc.sensors import SensorThresholds as SensorThresholds
Brad Bishop0b380f72016-06-10 00:29:50 -040015import obmc_system_config as System
Norman James323ed972015-12-09 09:06:37 -060016
17SENSOR_BUS = 'org.openbmc.Sensors'
18SENSOR_PATH = '/org/openbmc/sensors'
Norman James3bb97d92015-12-18 14:57:22 -060019DIR_POLL_INTERVAL = 30000
Norman James323ed972015-12-09 09:06:37 -060020HWMON_PATH = '/sys/class/hwmon'
21
22## static define which interface each property is under
23## need a better way that is not slow
24IFACE_LOOKUP = {
Brad Bishop2fa78fb2016-08-30 19:51:51 -040025 'units': SensorValue.IFACE_NAME,
26 'adjust': HwmonSensor.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,
33 'emergency_enabled': SensorThresholds.IFACE_NAME,
Norman James323ed972015-12-09 09:06:37 -060034}
35
Brad Bishop2fa78fb2016-08-30 19:51:51 -040036
Norman James323ed972015-12-09 09:06:37 -060037class Hwmons():
Brad Bishop2fa78fb2016-08-30 19:51:51 -040038 def __init__(self, bus):
39 self.sensors = {}
40 self.hwmon_root = {}
41 self.scanDirectory()
42 gobject.timeout_add(DIR_POLL_INTERVAL, self.scanDirectory)
Norman James323ed972015-12-09 09:06:37 -060043
Brad Bishop2fa78fb2016-08-30 19:51:51 -040044 def readAttribute(self, filename):
45 val = "-1"
46 try:
47 with open(filename, 'r') as f:
48 for line in f:
49 val = line.rstrip('\n')
50 except (OSError, IOError):
51 print "Cannot read attributes:", filename
52 return val
Norman James323ed972015-12-09 09:06:37 -060053
Brad Bishop2fa78fb2016-08-30 19:51:51 -040054 def writeAttribute(self, filename, value):
55 with open(filename, 'w') as f:
56 f.write(str(value)+'\n')
57
58 def poll(self, objpath, attribute):
59 try:
60 raw_value = int(self.readAttribute(attribute))
61 obj = bus.get_object(SENSOR_BUS, objpath, introspect=False)
62 intf = dbus.Interface(obj, HwmonSensor.IFACE_NAME)
63 rtn = intf.setByPoll(raw_value)
64 if rtn[0]:
65 self.writeAttribute(attribute, rtn[1])
66 except:
67 print "HWMON: Attibute no longer exists: "+attribute
68 self.sensors.pop(objpath, None)
69 return False
70
71 return True
72
73 def addObject(self, dpath, hwmon_path, hwmon):
74 objsuf = hwmon['object_path']
75 objpath = SENSOR_PATH+'/'+objsuf
76
77 if objpath not in self.sensors:
78 print "HWMON add: "+objpath+" : "+hwmon_path
79
80 ## register object with sensor manager
81 obj = bus.get_object(SENSOR_BUS, SENSOR_PATH, introspect=False)
82 intf = dbus.Interface(obj, SENSOR_BUS)
83 intf.register("HwmonSensor", objpath)
84
85 ## set some properties in dbus object
86 obj = bus.get_object(SENSOR_BUS, objpath, introspect=False)
87 intf = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
88 intf.Set(HwmonSensor.IFACE_NAME, 'filename', hwmon_path)
89
90 ## check if one of thresholds is defined to know
91 ## whether to enable thresholds or not
92 if 'critical_upper' in hwmon:
93 intf.Set(
94 SensorThresholds.IFACE_NAME, 'thresholds_enabled', True)
95
96 for prop in hwmon.keys():
97 if prop in IFACE_LOOKUP:
98 intf.Set(IFACE_LOOKUP[prop], prop, hwmon[prop])
99 print "Setting: "+prop+" = "+str(hwmon[prop])
100
101 self.sensors[objpath] = True
102 self.hwmon_root[dpath].append(objpath)
103 gobject.timeout_add(
104 hwmon['poll_interval'], self.poll, objpath, hwmon_path)
105
106 def scanDirectory(self):
107 devices = os.listdir(HWMON_PATH)
108 found_hwmon = {}
109 regx = re.compile('([a-z]+)\d+\_')
110 for d in devices:
111 dpath = HWMON_PATH+'/'+d+'/'
112 found_hwmon[dpath] = True
113 if dpath not in self.hwmon_root:
114 self.hwmon_root[dpath] = []
115 ## the instance name is a soft link
116 instance_name = os.path.realpath(dpath+'device').split('/').pop()
117
118 if instance_name in System.HWMON_CONFIG:
119 hwmon = System.HWMON_CONFIG[instance_name]
120
121 if 'labels' in hwmon:
122 label_files = glob.glob(dpath+'/*_label')
123 for f in label_files:
124 label_key = self.readAttribute(f)
125 if label_key in hwmon['labels']:
126 namef = f.replace('_label', '_input')
127 self.addObject(
128 dpath, namef, hwmon['labels'][label_key])
129 else:
130 pass
131
132 if 'names' in hwmon:
133 for attribute in hwmon['names'].keys():
134 self.addObject(
135 dpath, dpath+attribute, hwmon['names'][attribute])
136
137 else:
138 print "WARNING - hwmon: Unhandled hwmon: "+dpath
139
140 for k in self.hwmon_root.keys():
141 if k not in found_hwmon:
142 ## need to remove all objects associated with this path
143 print "Removing: "+k
144 for objpath in self.hwmon_root[k]:
145 if objpath in self.sensors:
146 print "HWMON remove: "+objpath
147 self.sensors.pop(objpath, None)
148 obj = bus.get_object(
149 SENSOR_BUS, SENSOR_PATH, introspect=False)
150 intf = dbus.Interface(obj, SENSOR_BUS)
151 intf.delete(objpath)
152
153 self.hwmon_root.pop(k, None)
154
155 return True
Norman James323ed972015-12-09 09:06:37 -0600156
157
Norman James323ed972015-12-09 09:06:37 -0600158if __name__ == '__main__':
Brad Bishop2fa78fb2016-08-30 19:51:51 -0400159 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
160 bus = get_dbus()
161 root_sensor = Hwmons(bus)
162 mainloop = gobject.MainLoop()
Norman James323ed972015-12-09 09:06:37 -0600163
Brad Bishop2fa78fb2016-08-30 19:51:51 -0400164 print "Starting HWMON sensors"
165 mainloop.run()