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