Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 1 | #!/usr/bin/python -u |
| 2 | |
| 3 | import sys |
| 4 | import os |
| 5 | import gobject |
Norman James | 3bb97d9 | 2015-12-18 14:57:22 -0600 | [diff] [blame] | 6 | import glob |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 7 | import dbus |
| 8 | import dbus.service |
| 9 | import dbus.mainloop.glib |
Norman James | 3bb97d9 | 2015-12-18 14:57:22 -0600 | [diff] [blame] | 10 | import re |
Brad Bishop | 84e73b5 | 2016-05-12 15:57:52 -0400 | [diff] [blame] | 11 | from obmc.dbuslib.bindings import get_dbus |
Norman James | 3bb97d9 | 2015-12-18 14:57:22 -0600 | [diff] [blame] | 12 | |
Brad Bishop | ee1b154 | 2016-05-12 16:55:00 -0400 | [diff] [blame] | 13 | from obmc.sensors import SensorValue as SensorValue |
| 14 | from obmc.sensors import HwmonSensor as HwmonSensor |
| 15 | from obmc.sensors import SensorThresholds as SensorThresholds |
Brad Bishop | 0b380f7 | 2016-06-10 00:29:50 -0400 | [diff] [blame] | 16 | import obmc_system_config as System |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 17 | |
| 18 | SENSOR_BUS = 'org.openbmc.Sensors' |
| 19 | SENSOR_PATH = '/org/openbmc/sensors' |
Norman James | 3bb97d9 | 2015-12-18 14:57:22 -0600 | [diff] [blame] | 20 | DIR_POLL_INTERVAL = 30000 |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 21 | HWMON_PATH = '/sys/class/hwmon' |
| 22 | |
| 23 | ## static define which interface each property is under |
| 24 | ## need a better way that is not slow |
| 25 | IFACE_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 James | 72567ba | 2016-01-13 16:57:48 -0600 | [diff] [blame] | 33 | 'emergency_enabled' : SensorThresholds.IFACE_NAME, |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 34 | } |
| 35 | |
| 36 | class 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 Bishop | efc6897 | 2016-06-05 17:56:20 -0400 | [diff] [blame] | 42 | self.cache = {} |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 43 | |
| 44 | def readAttribute(self,filename): |
Ken | 6956bbd | 2016-06-08 14:50:59 +0800 | [diff] [blame] | 45 | val = "-1" |
| 46 | try: |
Brad Bishop | 7dc8989 | 2016-06-14 18:18:19 -0400 | [diff] [blame] | 47 | with open(filename, 'r') as f: |
| 48 | for line in f: |
| 49 | val = line.rstrip('\n') |
Ken | 6956bbd | 2016-06-08 14:50:59 +0800 | [diff] [blame] | 50 | except (OSError, IOError): |
Brad Bishop | 7dc8989 | 2016-06-14 18:18:19 -0400 | [diff] [blame] | 51 | print "Cannot read attributes:", filename |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 52 | return val |
| 53 | |
| 54 | def writeAttribute(self,filename,value): |
| 55 | with open(filename, 'w') as f: |
| 56 | f.write(str(value)+'\n') |
| 57 | |
Brad Bishop | 8224ff8 | 2016-06-14 22:03:41 -0400 | [diff] [blame] | 58 | def should_update(self, attribute, value): |
Brad Bishop | efc6897 | 2016-06-05 17:56:20 -0400 | [diff] [blame] | 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 James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 67 | |
| 68 | def poll(self,objpath,attribute): |
| 69 | try: |
| 70 | raw_value = int(self.readAttribute(attribute)) |
Brad Bishop | efc6897 | 2016-06-05 17:56:20 -0400 | [diff] [blame] | 71 | 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 James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 77 | except: |
| 78 | print "HWMON: Attibute no longer exists: "+attribute |
Ken | 6956bbd | 2016-06-08 14:50:59 +0800 | [diff] [blame] | 79 | self.sensors.pop(objpath,None) |
Brad Bishop | efc6897 | 2016-06-05 17:56:20 -0400 | [diff] [blame] | 80 | if attribute in self.cache: |
| 81 | del self.cache[attribute] |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 82 | return False |
| 83 | |
| 84 | |
| 85 | return True |
| 86 | |
| 87 | |
Norman James | 3bb97d9 | 2015-12-18 14:57:22 -0600 | [diff] [blame] | 88 | def addObject(self,dpath,hwmon_path,hwmon): |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 89 | objsuf = hwmon['object_path'] |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 90 | objpath = SENSOR_PATH+'/'+objsuf |
Norman James | 3bb97d9 | 2015-12-18 14:57:22 -0600 | [diff] [blame] | 91 | |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 92 | if (self.sensors.has_key(objpath) == False): |
Norman James | 3bb97d9 | 2015-12-18 14:57:22 -0600 | [diff] [blame] | 93 | 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 James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 104 | |
Norman James | 3bb97d9 | 2015-12-18 14:57:22 -0600 | [diff] [blame] | 105 | ## 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 James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 109 | |
Norman James | 3bb97d9 | 2015-12-18 14:57:22 -0600 | [diff] [blame] | 110 | 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 James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 114 | |
Norman James | 3bb97d9 | 2015-12-18 14:57:22 -0600 | [diff] [blame] | 115 | self.sensors[objpath]=True |
| 116 | self.hwmon_root[dpath].append(objpath) |
| 117 | gobject.timeout_add(hwmon['poll_interval'],self.poll,objpath,hwmon_path) |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 118 | |
| 119 | def scanDirectory(self): |
| 120 | devices = os.listdir(HWMON_PATH) |
| 121 | found_hwmon = {} |
Norman James | 3bb97d9 | 2015-12-18 14:57:22 -0600 | [diff] [blame] | 122 | regx = re.compile('([a-z]+)\d+\_') |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 123 | 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 James | 3bb97d9 | 2015-12-18 14:57:22 -0600 | [diff] [blame] | 130 | |
| 131 | |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 132 | if (System.HWMON_CONFIG.has_key(instance_name)): |
Norman James | 3bb97d9 | 2015-12-18 14:57:22 -0600 | [diff] [blame] | 133 | 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 James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 150 | else: |
Norman James | 3bb97d9 | 2015-12-18 14:57:22 -0600 | [diff] [blame] | 151 | print "WARNING - hwmon: Unhandled hwmon: "+dpath |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 152 | |
| 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 James | 3bb97d9 | 2015-12-18 14:57:22 -0600 | [diff] [blame] | 162 | obj = bus.get_object(SENSOR_BUS,SENSOR_PATH,introspect=False) |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 163 | intf = dbus.Interface(obj,SENSOR_BUS) |
| 164 | intf.delete(objpath) |
| 165 | |
| 166 | self.hwmon_root.pop(k,None) |
| 167 | |
| 168 | return True |
| 169 | |
| 170 | |
| 171 | if __name__ == '__main__': |
| 172 | |
| 173 | dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) |
Brad Bishop | 84e73b5 | 2016-05-12 15:57:52 -0400 | [diff] [blame] | 174 | bus = get_dbus() |
Norman James | 323ed97 | 2015-12-09 09:06:37 -0600 | [diff] [blame] | 175 | root_sensor = Hwmons(bus) |
| 176 | mainloop = gobject.MainLoop() |
| 177 | |
| 178 | print "Starting HWMON sensors" |
| 179 | mainloop.run() |
| 180 | |