1// Copyright 2018 The Prometheus Authors 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14// +build linux 15 16package sysfs 17 18import ( 19 "fmt" 20 "io/ioutil" 21 "os" 22 "path/filepath" 23 24 "github.com/prometheus/procfs/internal/util" 25) 26 27// PowerSupply contains info from files in /sys/class/power_supply for a 28// single power supply. 29type PowerSupply struct { 30 Name string // Power Supply Name 31 Authentic *int64 // /sys/class/power_supply/<Name>/authentic 32 Calibrate *int64 // /sys/class/power_supply/<Name>/calibrate 33 Capacity *int64 // /sys/class/power_supply/<Name>/capacity 34 CapacityAlertMax *int64 // /sys/class/power_supply/<Name>/capacity_alert_max 35 CapacityAlertMin *int64 // /sys/class/power_supply/<Name>/capacity_alert_min 36 CapacityLevel string // /sys/class/power_supply/<Name>/capacity_level 37 ChargeAvg *int64 // /sys/class/power_supply/<Name>/charge_avg 38 ChargeControlLimit *int64 // /sys/class/power_supply/<Name>/charge_control_limit 39 ChargeControlLimitMax *int64 // /sys/class/power_supply/<Name>/charge_control_limit_max 40 ChargeCounter *int64 // /sys/class/power_supply/<Name>/charge_counter 41 ChargeEmpty *int64 // /sys/class/power_supply/<Name>/charge_empty 42 ChargeEmptyDesign *int64 // /sys/class/power_supply/<Name>/charge_empty_design 43 ChargeFull *int64 // /sys/class/power_supply/<Name>/charge_full 44 ChargeFullDesign *int64 // /sys/class/power_supply/<Name>/charge_full_design 45 ChargeNow *int64 // /sys/class/power_supply/<Name>/charge_now 46 ChargeTermCurrent *int64 // /sys/class/power_supply/<Name>/charge_term_current 47 ChargeType string // /sys/class/power_supply/<Name>/charge_type 48 ConstantChargeCurrent *int64 // /sys/class/power_supply/<Name>/constant_charge_current 49 ConstantChargeCurrentMax *int64 // /sys/class/power_supply/<Name>/constant_charge_current_max 50 ConstantChargeVoltage *int64 // /sys/class/power_supply/<Name>/constant_charge_voltage 51 ConstantChargeVoltageMax *int64 // /sys/class/power_supply/<Name>/constant_charge_voltage_max 52 CurrentAvg *int64 // /sys/class/power_supply/<Name>/current_avg 53 CurrentBoot *int64 // /sys/class/power_supply/<Name>/current_boot 54 CurrentMax *int64 // /sys/class/power_supply/<Name>/current_max 55 CurrentNow *int64 // /sys/class/power_supply/<Name>/current_now 56 CycleCount *int64 // /sys/class/power_supply/<Name>/cycle_count 57 EnergyAvg *int64 // /sys/class/power_supply/<Name>/energy_avg 58 EnergyEmpty *int64 // /sys/class/power_supply/<Name>/energy_empty 59 EnergyEmptyDesign *int64 // /sys/class/power_supply/<Name>/energy_empty_design 60 EnergyFull *int64 // /sys/class/power_supply/<Name>/energy_full 61 EnergyFullDesign *int64 // /sys/class/power_supply/<Name>/energy_full_design 62 EnergyNow *int64 // /sys/class/power_supply/<Name>/energy_now 63 Health string // /sys/class/power_supply/<Name>/health 64 InputCurrentLimit *int64 // /sys/class/power_supply/<Name>/input_current_limit 65 Manufacturer string // /sys/class/power_supply/<Name>/manufacturer 66 ModelName string // /sys/class/power_supply/<Name>/model_name 67 Online *int64 // /sys/class/power_supply/<Name>/online 68 PowerAvg *int64 // /sys/class/power_supply/<Name>/power_avg 69 PowerNow *int64 // /sys/class/power_supply/<Name>/power_now 70 PrechargeCurrent *int64 // /sys/class/power_supply/<Name>/precharge_current 71 Present *int64 // /sys/class/power_supply/<Name>/present 72 Scope string // /sys/class/power_supply/<Name>/scope 73 SerialNumber string // /sys/class/power_supply/<Name>/serial_number 74 Status string // /sys/class/power_supply/<Name>/status 75 Technology string // /sys/class/power_supply/<Name>/technology 76 Temp *int64 // /sys/class/power_supply/<Name>/temp 77 TempAlertMax *int64 // /sys/class/power_supply/<Name>/temp_alert_max 78 TempAlertMin *int64 // /sys/class/power_supply/<Name>/temp_alert_min 79 TempAmbient *int64 // /sys/class/power_supply/<Name>/temp_ambient 80 TempAmbientMax *int64 // /sys/class/power_supply/<Name>/temp_ambient_max 81 TempAmbientMin *int64 // /sys/class/power_supply/<Name>/temp_ambient_min 82 TempMax *int64 // /sys/class/power_supply/<Name>/temp_max 83 TempMin *int64 // /sys/class/power_supply/<Name>/temp_min 84 TimeToEmptyAvg *int64 // /sys/class/power_supply/<Name>/time_to_empty_avg 85 TimeToEmptyNow *int64 // /sys/class/power_supply/<Name>/time_to_empty_now 86 TimeToFullAvg *int64 // /sys/class/power_supply/<Name>/time_to_full_avg 87 TimeToFullNow *int64 // /sys/class/power_supply/<Name>/time_to_full_now 88 Type string // /sys/class/power_supply/<Name>/type 89 UsbType string // /sys/class/power_supply/<Name>/usb_type 90 VoltageAvg *int64 // /sys/class/power_supply/<Name>/voltage_avg 91 VoltageBoot *int64 // /sys/class/power_supply/<Name>/voltage_boot 92 VoltageMax *int64 // /sys/class/power_supply/<Name>/voltage_max 93 VoltageMaxDesign *int64 // /sys/class/power_supply/<Name>/voltage_max_design 94 VoltageMin *int64 // /sys/class/power_supply/<Name>/voltage_min 95 VoltageMinDesign *int64 // /sys/class/power_supply/<Name>/voltage_min_design 96 VoltageNow *int64 // /sys/class/power_supply/<Name>/voltage_now 97 VoltageOCV *int64 // /sys/class/power_supply/<Name>/voltage_ocv 98} 99 100// PowerSupplyClass is a collection of every power supply in 101// /sys/class/power_supply. 102// 103// The map keys are the names of the power supplies. 104type PowerSupplyClass map[string]PowerSupply 105 106// PowerSupplyClass returns info for all power supplies read from 107// /sys/class/power_supply. 108func (fs FS) PowerSupplyClass() (PowerSupplyClass, error) { 109 path := fs.sys.Path("class/power_supply") 110 111 dirs, err := ioutil.ReadDir(path) 112 if err != nil { 113 return nil, err 114 } 115 116 psc := make(PowerSupplyClass, len(dirs)) 117 for _, d := range dirs { 118 ps, err := parsePowerSupply(filepath.Join(path, d.Name())) 119 if err != nil { 120 return nil, err 121 } 122 123 ps.Name = d.Name() 124 psc[d.Name()] = *ps 125 } 126 127 return psc, nil 128} 129 130func parsePowerSupply(path string) (*PowerSupply, error) { 131 files, err := ioutil.ReadDir(path) 132 if err != nil { 133 return nil, err 134 } 135 136 var ps PowerSupply 137 for _, f := range files { 138 if !f.Mode().IsRegular() { 139 continue 140 } 141 142 name := filepath.Join(path, f.Name()) 143 value, err := util.SysReadFile(name) 144 if err != nil { 145 if os.IsNotExist(err) || err.Error() == "operation not supported" || err.Error() == "invalid argument" { 146 continue 147 } 148 return nil, fmt.Errorf("failed to read file %q: %w", name, err) 149 } 150 151 vp := util.NewValueParser(value) 152 153 switch f.Name() { 154 case "authentic": 155 ps.Authentic = vp.PInt64() 156 case "calibrate": 157 ps.Calibrate = vp.PInt64() 158 case "capacity": 159 ps.Capacity = vp.PInt64() 160 case "capacity_alert_max": 161 ps.CapacityAlertMax = vp.PInt64() 162 case "capacity_alert_min": 163 ps.CapacityAlertMin = vp.PInt64() 164 case "capacity_level": 165 ps.CapacityLevel = value 166 case "charge_avg": 167 ps.ChargeAvg = vp.PInt64() 168 case "charge_control_limit": 169 ps.ChargeControlLimit = vp.PInt64() 170 case "charge_control_limit_max": 171 ps.ChargeControlLimitMax = vp.PInt64() 172 case "charge_counter": 173 ps.ChargeCounter = vp.PInt64() 174 case "charge_empty": 175 ps.ChargeEmpty = vp.PInt64() 176 case "charge_empty_design": 177 ps.ChargeEmptyDesign = vp.PInt64() 178 case "charge_full": 179 ps.ChargeFull = vp.PInt64() 180 case "charge_full_design": 181 ps.ChargeFullDesign = vp.PInt64() 182 case "charge_now": 183 ps.ChargeNow = vp.PInt64() 184 case "charge_term_current": 185 ps.ChargeTermCurrent = vp.PInt64() 186 case "charge_type": 187 ps.ChargeType = value 188 case "constant_charge_current": 189 ps.ConstantChargeCurrent = vp.PInt64() 190 case "constant_charge_current_max": 191 ps.ConstantChargeCurrentMax = vp.PInt64() 192 case "constant_charge_voltage": 193 ps.ConstantChargeVoltage = vp.PInt64() 194 case "constant_charge_voltage_max": 195 ps.ConstantChargeVoltageMax = vp.PInt64() 196 case "current_avg": 197 ps.CurrentAvg = vp.PInt64() 198 case "current_boot": 199 ps.CurrentBoot = vp.PInt64() 200 case "current_max": 201 ps.CurrentMax = vp.PInt64() 202 case "current_now": 203 ps.CurrentNow = vp.PInt64() 204 case "cycle_count": 205 ps.CycleCount = vp.PInt64() 206 case "energy_avg": 207 ps.EnergyAvg = vp.PInt64() 208 case "energy_empty": 209 ps.EnergyEmpty = vp.PInt64() 210 case "energy_empty_design": 211 ps.EnergyEmptyDesign = vp.PInt64() 212 case "energy_full": 213 ps.EnergyFull = vp.PInt64() 214 case "energy_full_design": 215 ps.EnergyFullDesign = vp.PInt64() 216 case "energy_now": 217 ps.EnergyNow = vp.PInt64() 218 case "health": 219 ps.Health = value 220 case "input_current_limit": 221 ps.InputCurrentLimit = vp.PInt64() 222 case "manufacturer": 223 ps.Manufacturer = value 224 case "model_name": 225 ps.ModelName = value 226 case "online": 227 ps.Online = vp.PInt64() 228 case "power_avg": 229 ps.PowerAvg = vp.PInt64() 230 case "power_now": 231 ps.PowerNow = vp.PInt64() 232 case "precharge_current": 233 ps.PrechargeCurrent = vp.PInt64() 234 case "present": 235 ps.Present = vp.PInt64() 236 case "scope": 237 ps.Scope = value 238 case "serial_number": 239 ps.SerialNumber = value 240 case "status": 241 ps.Status = value 242 case "technology": 243 ps.Technology = value 244 case "temp": 245 ps.Temp = vp.PInt64() 246 case "temp_alert_max": 247 ps.TempAlertMax = vp.PInt64() 248 case "temp_alert_min": 249 ps.TempAlertMin = vp.PInt64() 250 case "temp_ambient": 251 ps.TempAmbient = vp.PInt64() 252 case "temp_ambient_max": 253 ps.TempAmbientMax = vp.PInt64() 254 case "temp_ambient_min": 255 ps.TempAmbientMin = vp.PInt64() 256 case "temp_max": 257 ps.TempMax = vp.PInt64() 258 case "temp_min": 259 ps.TempMin = vp.PInt64() 260 case "time_to_empty_avg": 261 ps.TimeToEmptyAvg = vp.PInt64() 262 case "time_to_empty_now": 263 ps.TimeToEmptyNow = vp.PInt64() 264 case "time_to_full_avg": 265 ps.TimeToFullAvg = vp.PInt64() 266 case "time_to_full_now": 267 ps.TimeToFullNow = vp.PInt64() 268 case "type": 269 ps.Type = value 270 case "usb_type": 271 ps.UsbType = value 272 case "voltage_avg": 273 ps.VoltageAvg = vp.PInt64() 274 case "voltage_boot": 275 ps.VoltageBoot = vp.PInt64() 276 case "voltage_max": 277 ps.VoltageMax = vp.PInt64() 278 case "voltage_max_design": 279 ps.VoltageMaxDesign = vp.PInt64() 280 case "voltage_min": 281 ps.VoltageMin = vp.PInt64() 282 case "voltage_min_design": 283 ps.VoltageMinDesign = vp.PInt64() 284 case "voltage_now": 285 ps.VoltageNow = vp.PInt64() 286 case "voltage_ocv": 287 ps.VoltageOCV = vp.PInt64() 288 } 289 290 if err := vp.Err(); err != nil { 291 return nil, err 292 } 293 } 294 295 return &ps, nil 296} 297