1
2
3
4
5 package oshi.hardware.platform.windows;
6
7 import java.util.Locale;
8 import java.util.Objects;
9
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
12
13 import com.sun.jna.platform.win32.COM.COMException;
14 import com.sun.jna.platform.win32.COM.WbemcliUtil.WmiResult;
15
16 import oshi.annotation.concurrent.ThreadSafe;
17 import oshi.driver.windows.wmi.MSAcpiThermalZoneTemperature;
18 import oshi.driver.windows.wmi.MSAcpiThermalZoneTemperature.TemperatureProperty;
19 import oshi.driver.windows.wmi.OhmHardware;
20 import oshi.driver.windows.wmi.OhmHardware.IdentifierProperty;
21 import oshi.driver.windows.wmi.OhmSensor;
22 import oshi.driver.windows.wmi.OhmSensor.ValueProperty;
23 import oshi.driver.windows.wmi.Win32Fan;
24 import oshi.driver.windows.wmi.Win32Fan.SpeedProperty;
25 import oshi.driver.windows.wmi.Win32Processor;
26 import oshi.driver.windows.wmi.Win32Processor.VoltProperty;
27 import oshi.hardware.common.AbstractSensors;
28 import oshi.util.platform.windows.WmiQueryHandler;
29 import oshi.util.platform.windows.WmiUtil;
30
31
32
33
34 @ThreadSafe
35 final class WindowsSensors extends AbstractSensors {
36
37 private static final Logger LOG = LoggerFactory.getLogger(WindowsSensors.class);
38
39 private static final String COM_EXCEPTION_MSG = "COM exception: {}";
40
41 @Override
42 public double queryCpuTemperature() {
43
44
45
46 double tempC = getTempFromOHM();
47 if (tempC > 0d) {
48 return tempC;
49 }
50
51
52 tempC = getTempFromWMI();
53
54
55
56
57 return tempC;
58 }
59
60 private static double getTempFromOHM() {
61 WmiQueryHandler h = Objects.requireNonNull(WmiQueryHandler.createInstance());
62 boolean comInit = false;
63 try {
64 comInit = h.initCOM();
65 WmiResult<IdentifierProperty> ohmHardware = OhmHardware.queryHwIdentifier(h, "Hardware", "CPU");
66 if (ohmHardware.getResultCount() > 0) {
67 LOG.debug("Found Temperature data in Open Hardware Monitor");
68 String cpuIdentifier = WmiUtil.getString(ohmHardware, IdentifierProperty.IDENTIFIER, 0);
69 if (cpuIdentifier.length() > 0) {
70 WmiResult<ValueProperty> ohmSensors = OhmSensor.querySensorValue(h, cpuIdentifier, "Temperature");
71 if (ohmSensors.getResultCount() > 0) {
72 double sum = 0;
73 for (int i = 0; i < ohmSensors.getResultCount(); i++) {
74 sum += WmiUtil.getFloat(ohmSensors, ValueProperty.VALUE, i);
75 }
76 return sum / ohmSensors.getResultCount();
77 }
78 }
79 }
80 } catch (COMException e) {
81 LOG.warn(COM_EXCEPTION_MSG, e.getMessage());
82 } finally {
83 if (comInit) {
84 h.unInitCOM();
85 }
86 }
87 return 0;
88 }
89
90 private static double getTempFromWMI() {
91 double tempC = 0d;
92 long tempK = 0L;
93 WmiResult<TemperatureProperty> result = MSAcpiThermalZoneTemperature.queryCurrentTemperature();
94 if (result.getResultCount() > 0) {
95 LOG.debug("Found Temperature data in WMI");
96 tempK = WmiUtil.getUint32asLong(result, TemperatureProperty.CURRENTTEMPERATURE, 0);
97 }
98 if (tempK > 2732L) {
99 tempC = tempK / 10d - 273.15;
100 } else if (tempK > 274L) {
101 tempC = tempK - 273d;
102 }
103 return tempC < 0d ? 0d : tempC;
104 }
105
106 @Override
107 public int[] queryFanSpeeds() {
108
109 int[] fanSpeeds = getFansFromOHM();
110 if (fanSpeeds.length > 0) {
111 return fanSpeeds;
112 }
113
114
115
116 fanSpeeds = getFansFromWMI();
117 if (fanSpeeds.length > 0) {
118 return fanSpeeds;
119 }
120
121
122 return new int[0];
123 }
124
125 private static int[] getFansFromOHM() {
126 WmiQueryHandler h = Objects.requireNonNull(WmiQueryHandler.createInstance());
127 boolean comInit = false;
128 try {
129 comInit = h.initCOM();
130 WmiResult<IdentifierProperty> ohmHardware = OhmHardware.queryHwIdentifier(h, "Hardware", "CPU");
131 if (ohmHardware.getResultCount() > 0) {
132 LOG.debug("Found Fan data in Open Hardware Monitor");
133 String cpuIdentifier = WmiUtil.getString(ohmHardware, IdentifierProperty.IDENTIFIER, 0);
134 if (cpuIdentifier.length() > 0) {
135 WmiResult<ValueProperty> ohmSensors = OhmSensor.querySensorValue(h, cpuIdentifier, "Fan");
136 if (ohmSensors.getResultCount() > 0) {
137 int[] fanSpeeds = new int[ohmSensors.getResultCount()];
138 for (int i = 0; i < ohmSensors.getResultCount(); i++) {
139 fanSpeeds[i] = (int) WmiUtil.getFloat(ohmSensors, ValueProperty.VALUE, i);
140 }
141 return fanSpeeds;
142 }
143 }
144 }
145 } catch (COMException e) {
146 LOG.warn(COM_EXCEPTION_MSG, e.getMessage());
147 } finally {
148 if (comInit) {
149 h.unInitCOM();
150 }
151 }
152 return new int[0];
153 }
154
155 private static int[] getFansFromWMI() {
156 WmiResult<SpeedProperty> fan = Win32Fan.querySpeed();
157 if (fan.getResultCount() > 1) {
158 LOG.debug("Found Fan data in WMI");
159 int[] fanSpeeds = new int[fan.getResultCount()];
160 for (int i = 0; i < fan.getResultCount(); i++) {
161 fanSpeeds[i] = (int) WmiUtil.getUint64(fan, SpeedProperty.DESIREDSPEED, i);
162 }
163 return fanSpeeds;
164 }
165 return new int[0];
166 }
167
168 @Override
169 public double queryCpuVoltage() {
170
171 double volts = getVoltsFromOHM();
172 if (volts > 0d) {
173 return volts;
174 }
175
176
177
178 volts = getVoltsFromWMI();
179
180 return volts;
181 }
182
183 private static double getVoltsFromOHM() {
184 WmiQueryHandler h = Objects.requireNonNull(WmiQueryHandler.createInstance());
185 boolean comInit = false;
186 try {
187 comInit = h.initCOM();
188 WmiResult<IdentifierProperty> ohmHardware = OhmHardware.queryHwIdentifier(h, "Sensor", "Voltage");
189 if (ohmHardware.getResultCount() > 0) {
190 LOG.debug("Found Voltage data in Open Hardware Monitor");
191
192 String cpuIdentifier = null;
193 for (int i = 0; i < ohmHardware.getResultCount(); i++) {
194 String id = WmiUtil.getString(ohmHardware, IdentifierProperty.IDENTIFIER, i);
195 if (id.toLowerCase(Locale.ROOT).contains("cpu")) {
196 cpuIdentifier = id;
197 break;
198 }
199 }
200
201 if (cpuIdentifier == null) {
202 cpuIdentifier = WmiUtil.getString(ohmHardware, IdentifierProperty.IDENTIFIER, 0);
203 }
204
205 WmiResult<ValueProperty> ohmSensors = OhmSensor.querySensorValue(h, cpuIdentifier, "Voltage");
206 if (ohmSensors.getResultCount() > 0) {
207 return WmiUtil.getFloat(ohmSensors, ValueProperty.VALUE, 0);
208 }
209 }
210 } catch (COMException e) {
211 LOG.warn(COM_EXCEPTION_MSG, e.getMessage());
212 } finally {
213 if (comInit) {
214 h.unInitCOM();
215 }
216 }
217 return 0d;
218 }
219
220 private static double getVoltsFromWMI() {
221 WmiResult<VoltProperty> voltage = Win32Processor.queryVoltage();
222 if (voltage.getResultCount() > 1) {
223 LOG.debug("Found Voltage data in WMI");
224 int decivolts = WmiUtil.getUint16(voltage, VoltProperty.CURRENTVOLTAGE, 0);
225
226
227
228 if (decivolts > 0) {
229 if ((decivolts & 0x80) == 0) {
230 decivolts = WmiUtil.getUint32(voltage, VoltProperty.VOLTAGECAPS, 0);
231
232 if ((decivolts & 0x1) > 0) {
233 return 5.0;
234 } else if ((decivolts & 0x2) > 0) {
235 return 3.3;
236 } else if ((decivolts & 0x4) > 0) {
237 return 2.9;
238 }
239 } else {
240
241 return (decivolts & 0x7F) / 10d;
242 }
243 }
244 }
245 return 0d;
246 }
247 }