View Javadoc
1   /*
2    * Copyright 2016-2023 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.hardware.common;
6   
7   import java.time.LocalDate;
8   import java.util.List;
9   import java.util.Locale;
10  
11  import com.sun.jna.Platform;
12  
13  import oshi.SystemInfo;
14  import oshi.annotation.concurrent.ThreadSafe;
15  import oshi.hardware.PowerSource;
16  import oshi.hardware.platform.linux.LinuxPowerSource;
17  import oshi.hardware.platform.mac.MacPowerSource;
18  import oshi.hardware.platform.unix.aix.AixPowerSource;
19  import oshi.hardware.platform.unix.freebsd.FreeBsdPowerSource;
20  import oshi.hardware.platform.unix.solaris.SolarisPowerSource;
21  import oshi.hardware.platform.windows.WindowsPowerSource;
22  import oshi.util.Constants;
23  
24  /**
25   * A Power Source
26   */
27  @ThreadSafe
28  public abstract class AbstractPowerSource implements PowerSource {
29  
30      private String name;
31      private String deviceName;
32      private double remainingCapacityPercent;
33      private double timeRemainingEstimated;
34      private double timeRemainingInstant;
35      private double powerUsageRate;
36      private double voltage;
37      private double amperage;
38      private boolean powerOnLine;
39      private boolean charging;
40      private boolean discharging;
41      private CapacityUnits capacityUnits;
42      private int currentCapacity;
43      private int maxCapacity;
44      private int designCapacity;
45      private int cycleCount;
46      private String chemistry;
47      private LocalDate manufactureDate;
48      private String manufacturer;
49      private String serialNumber;
50      private double temperature;
51  
52      protected AbstractPowerSource(String name, String deviceName, double remainingCapacityPercent,
53              double timeRemainingEstimated, double timeRemainingInstant, double powerUsageRate, double voltage,
54              double amperage, boolean powerOnLine, boolean charging, boolean discharging, CapacityUnits capacityUnits,
55              int currentCapacity, int maxCapacity, int designCapacity, int cycleCount, String chemistry,
56              LocalDate manufactureDate, String manufacturer, String serialNumber, double temperature) {
57          super();
58          this.name = name;
59          this.deviceName = deviceName;
60          this.remainingCapacityPercent = remainingCapacityPercent;
61          this.timeRemainingEstimated = timeRemainingEstimated;
62          this.timeRemainingInstant = timeRemainingInstant;
63          this.powerUsageRate = powerUsageRate;
64          this.voltage = voltage;
65          this.amperage = amperage;
66          this.powerOnLine = powerOnLine;
67          this.charging = charging;
68          this.discharging = discharging;
69          this.capacityUnits = capacityUnits;
70          this.currentCapacity = currentCapacity;
71          this.maxCapacity = maxCapacity;
72          this.designCapacity = designCapacity;
73          this.cycleCount = cycleCount;
74          this.chemistry = chemistry;
75          this.manufactureDate = manufactureDate;
76          this.manufacturer = manufacturer;
77          this.serialNumber = serialNumber;
78          this.temperature = temperature;
79      }
80  
81      @Override
82      public String getName() {
83          return this.name;
84      }
85  
86      @Override
87      public String getDeviceName() {
88          return this.deviceName;
89      }
90  
91      @Override
92      public double getRemainingCapacityPercent() {
93          return this.remainingCapacityPercent;
94      }
95  
96      @Override
97      public double getTimeRemainingEstimated() {
98          return this.timeRemainingEstimated;
99      }
100 
101     @Override
102     public double getTimeRemainingInstant() {
103         return this.timeRemainingInstant;
104     }
105 
106     @Override
107     public double getPowerUsageRate() {
108         return this.powerUsageRate;
109     }
110 
111     @Override
112     public double getVoltage() {
113         return this.voltage;
114     }
115 
116     @Override
117     public double getAmperage() {
118         return this.amperage;
119     }
120 
121     @Override
122     public boolean isPowerOnLine() {
123         return this.powerOnLine;
124     }
125 
126     @Override
127     public boolean isCharging() {
128         return this.charging;
129     }
130 
131     @Override
132     public boolean isDischarging() {
133         return this.discharging;
134     }
135 
136     @Override
137     public CapacityUnits getCapacityUnits() {
138         return this.capacityUnits;
139     }
140 
141     @Override
142     public int getCurrentCapacity() {
143         return this.currentCapacity;
144     }
145 
146     @Override
147     public int getMaxCapacity() {
148         return this.maxCapacity;
149     }
150 
151     @Override
152     public int getDesignCapacity() {
153         return this.designCapacity;
154     }
155 
156     @Override
157     public int getCycleCount() {
158         return this.cycleCount;
159     }
160 
161     @Override
162     public String getChemistry() {
163         return this.chemistry;
164     }
165 
166     @Override
167     public LocalDate getManufactureDate() {
168         return this.manufactureDate;
169     }
170 
171     @Override
172     public String getManufacturer() {
173         return this.manufacturer;
174     }
175 
176     @Override
177     public String getSerialNumber() {
178         return this.serialNumber;
179     }
180 
181     @Override
182     public double getTemperature() {
183         return this.temperature;
184     }
185 
186     @Override
187     public boolean updateAttributes() {
188         List<PowerSource> psArr = getPowerSources();
189         for (PowerSource ps : psArr) {
190             if (ps.getName().equals(this.name)) {
191                 this.name = ps.getName();
192                 this.deviceName = ps.getDeviceName();
193                 this.remainingCapacityPercent = ps.getRemainingCapacityPercent();
194                 this.timeRemainingEstimated = ps.getTimeRemainingEstimated();
195                 this.timeRemainingInstant = ps.getTimeRemainingInstant();
196                 this.powerUsageRate = ps.getPowerUsageRate();
197                 this.voltage = ps.getVoltage();
198                 this.amperage = ps.getAmperage();
199                 this.powerOnLine = ps.isPowerOnLine();
200                 this.charging = ps.isCharging();
201                 this.discharging = ps.isDischarging();
202                 this.capacityUnits = ps.getCapacityUnits();
203                 this.currentCapacity = ps.getCurrentCapacity();
204                 this.maxCapacity = ps.getMaxCapacity();
205                 this.designCapacity = ps.getDesignCapacity();
206                 this.cycleCount = ps.getCycleCount();
207                 this.chemistry = ps.getChemistry();
208                 this.manufactureDate = ps.getManufactureDate();
209                 this.manufacturer = ps.getManufacturer();
210                 this.serialNumber = ps.getSerialNumber();
211                 this.temperature = ps.getTemperature();
212                 return true;
213             }
214         }
215         // Didn't find this battery
216         return false;
217     }
218 
219     private static List<PowerSource> getPowerSources() {
220         switch (SystemInfo.getCurrentPlatform()) {
221         case WINDOWS:
222             return WindowsPowerSource.getPowerSources();
223         case MACOS:
224             return MacPowerSource.getPowerSources();
225         case LINUX:
226             return LinuxPowerSource.getPowerSources();
227         case SOLARIS:
228             return SolarisPowerSource.getPowerSources();
229         case FREEBSD:
230             return FreeBsdPowerSource.getPowerSources();
231         case AIX:
232             return AixPowerSource.getPowerSources();
233         default:
234             throw new UnsupportedOperationException("Operating system not supported: " + Platform.getOSType());
235         }
236     }
237 
238     @Override
239     public String toString() {
240         StringBuilder sb = new StringBuilder();
241         sb.append("Name: ").append(getName()).append(", ");
242         sb.append("Device Name: ").append(getDeviceName()).append(",\n ");
243         sb.append("RemainingCapacityPercent: ").append(getRemainingCapacityPercent() * 100).append("%, ");
244         sb.append("Time Remaining: ").append(formatTimeRemaining(getTimeRemainingEstimated())).append(", ");
245         sb.append("Time Remaining Instant: ").append(formatTimeRemaining(getTimeRemainingInstant())).append(",\n ");
246         sb.append("Power Usage Rate: ").append(getPowerUsageRate()).append("mW, ");
247         sb.append("Voltage: ");
248         if (getVoltage() > 0) {
249             sb.append(getVoltage()).append("V, ");
250         } else {
251             sb.append(Constants.UNKNOWN).append(", ");
252         }
253         sb.append("Amperage: ").append(getAmperage()).append("mA,\n ");
254         sb.append("Power OnLine: ").append(isPowerOnLine()).append(", ");
255         sb.append("Charging: ").append(isCharging()).append(", ");
256         sb.append("Discharging: ").append(isDischarging()).append(",\n ");
257         sb.append("Capacity Units: ").append(getCapacityUnits()).append(", ");
258         sb.append("Current Capacity: ").append(getCurrentCapacity()).append(", ");
259         sb.append("Max Capacity: ").append(getMaxCapacity()).append(", ");
260         sb.append("Design Capacity: ").append(getDesignCapacity()).append(",\n ");
261         sb.append("Cycle Count: ").append(getCycleCount()).append(", ");
262         sb.append("Chemistry: ").append(getChemistry()).append(", ");
263         sb.append("Manufacture Date: ").append(getManufactureDate() != null ? getManufactureDate() : Constants.UNKNOWN)
264                 .append(", ");
265         sb.append("Manufacturer: ").append(getManufacturer()).append(",\n ");
266         sb.append("SerialNumber: ").append(getSerialNumber()).append(", ");
267         sb.append("Temperature: ");
268         if (getTemperature() > 0) {
269             sb.append(getTemperature()).append("°C");
270         } else {
271             sb.append(Constants.UNKNOWN);
272         }
273         return sb.toString();
274     }
275 
276     /**
277      * Estimated time remaining on power source, formatted as HH:mm
278      *
279      * @param timeInSeconds The time remaining, in seconds
280      * @return formatted String of time remaining
281      */
282     private static String formatTimeRemaining(double timeInSeconds) {
283         String formattedTimeRemaining;
284         if (timeInSeconds < -1.5) {
285             formattedTimeRemaining = "Charging";
286         } else if (timeInSeconds < 0) {
287             formattedTimeRemaining = "Unknown";
288         } else {
289             int hours = (int) (timeInSeconds / 3600);
290             int minutes = (int) (timeInSeconds % 3600 / 60);
291             formattedTimeRemaining = String.format(Locale.ROOT, "%d:%02d", hours, minutes);
292         }
293         return formattedTimeRemaining;
294     }
295 }