Add battery remaining time sensor (#660)
This commit is contained in:
@@ -23,6 +23,7 @@ namespace LibreHardwareMonitor.Hardware.Battery
|
||||
private readonly Sensor _designedCapacity;
|
||||
private readonly Sensor _fullChargedCapacity;
|
||||
private readonly Sensor _remainingCapacity;
|
||||
private readonly Sensor _remainingTime;
|
||||
private readonly Sensor _voltage;
|
||||
|
||||
public Battery
|
||||
@@ -98,6 +99,9 @@ namespace LibreHardwareMonitor.Hardware.Battery
|
||||
|
||||
_degradationPercentage = new Sensor("Degradation Level", 0, SensorType.Level, this, settings);
|
||||
ActivateSensor(_degradationPercentage);
|
||||
|
||||
_remainingTime = new Sensor("Remaining Time (Estimated)", 0, SensorType.TimeSpan, this, settings);
|
||||
ActivateSensor(_remainingTime);
|
||||
}
|
||||
|
||||
public float ChargeDischargeCurrent { get; private set; }
|
||||
@@ -120,6 +124,8 @@ namespace LibreHardwareMonitor.Hardware.Battery
|
||||
|
||||
public float RemainingCapacity { get; private set; }
|
||||
|
||||
public uint RemainingTime { get; private set; }
|
||||
|
||||
public float Voltage { get; private set; }
|
||||
|
||||
public override void Update()
|
||||
@@ -184,6 +190,31 @@ namespace LibreHardwareMonitor.Hardware.Battery
|
||||
|
||||
_degradationPercentage.Value = 100f - (_fullChargedCapacity.Value * 100f / _designedCapacity.Value);
|
||||
}
|
||||
|
||||
uint estimatedRunTime = 0;
|
||||
Kernel32.BATTERY_QUERY_INFORMATION bqi = default;
|
||||
bqi.BatteryTag = _batteryTag;
|
||||
bqi.InformationLevel = Kernel32.BATTERY_QUERY_INFORMATION_LEVEL.BatteryEstimatedTime;
|
||||
if (Kernel32.DeviceIoControl(_batteryHandle,
|
||||
Kernel32.IOCTL.IOCTL_BATTERY_QUERY_INFORMATION,
|
||||
ref bqi,
|
||||
Marshal.SizeOf(bqi),
|
||||
ref estimatedRunTime,
|
||||
Marshal.SizeOf<uint>(),
|
||||
out _,
|
||||
IntPtr.Zero))
|
||||
{
|
||||
RemainingTime = estimatedRunTime;
|
||||
if (estimatedRunTime != Kernel32.BATTERY_UNKNOWN_TIME)
|
||||
{
|
||||
ActivateSensor(_remainingTime);
|
||||
_remainingTime.Value = estimatedRunTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
DeactivateSensor(_remainingTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace LibreHardwareMonitor.Hardware.Battery
|
||||
IntPtr hdev = SetupApi.SetupDiGetClassDevs(ref SetupApi.GUID_DEVICE_BATTERY, IntPtr.Zero, IntPtr.Zero, SetupApi.DIGCF_PRESENT | SetupApi.DIGCF_DEVICEINTERFACE);
|
||||
if (hdev != SetupApi.INVALID_HANDLE_VALUE)
|
||||
{
|
||||
for (uint i = 0;; i++)
|
||||
for (uint i = 0; ; i++)
|
||||
{
|
||||
SetupApi.SP_DEVICE_INTERFACE_DATA did = default;
|
||||
did.cbSize = (uint)Marshal.SizeOf(typeof(SetupApi.SP_DEVICE_INTERFACE_DATA));
|
||||
@@ -198,6 +198,11 @@ namespace LibreHardwareMonitor.Hardware.Battery
|
||||
.Append(" Charge Level: ").AppendFormat("{0:F2}", bat.RemainingCapacity * 100f / bat.FullChargedCapacity).AppendLine(" %")
|
||||
.Append(" Voltage: ").AppendFormat("{0:F3}", bat.Voltage).AppendLine(" V");
|
||||
|
||||
if (bat.RemainingTime != Kernel32.BATTERY_UNKNOWN_TIME)
|
||||
{
|
||||
reportBuilder.Append(" Remaining Time (Estimated): ").AppendFormat("{0:g}", TimeSpan.FromSeconds(bat.RemainingTime)).AppendLine();
|
||||
}
|
||||
|
||||
switch (bat.ChargeDischargeRate)
|
||||
{
|
||||
case > 0:
|
||||
|
||||
@@ -29,6 +29,8 @@ namespace LibreHardwareMonitor.Interop
|
||||
|
||||
internal const uint LPTR = 0x0000 | 0x0040;
|
||||
|
||||
internal const uint BATTERY_UNKNOWN_TIME = 0xFFFFFFFF;
|
||||
|
||||
private const string DllName = "kernel32.dll";
|
||||
|
||||
[Flags]
|
||||
@@ -258,6 +260,19 @@ namespace LibreHardwareMonitor.Interop
|
||||
out uint lpBytesReturned,
|
||||
IntPtr lpOverlapped);
|
||||
|
||||
[DllImport(DllName, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool DeviceIoControl
|
||||
(
|
||||
SafeFileHandle hDevice,
|
||||
IOCTL dwIoControlCode,
|
||||
ref BATTERY_QUERY_INFORMATION lpInBuffer,
|
||||
int nInBufferSize,
|
||||
ref uint lpOutBuffer,
|
||||
int nOutBufferSize,
|
||||
out uint lpBytesReturned,
|
||||
IntPtr lpOverlapped);
|
||||
|
||||
[DllImport(DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
internal static extern IntPtr LocalAlloc(uint uFlags, ulong uBytes);
|
||||
|
||||
@@ -275,7 +290,7 @@ namespace LibreHardwareMonitor.Interop
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true)]
|
||||
internal static extern IntPtr GetProcAddress(IntPtr module, string methodName);
|
||||
|
||||
|
||||
[DllImport(DllName)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool FreeLibrary(IntPtr module);
|
||||
@@ -285,7 +300,7 @@ namespace LibreHardwareMonitor.Interop
|
||||
|
||||
[DllImport(DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
internal static extern IntPtr GetCurrentThread();
|
||||
|
||||
|
||||
[DllImport(DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
public static extern ushort GetActiveProcessorGroupCount();
|
||||
|
||||
@@ -303,9 +318,9 @@ namespace LibreHardwareMonitor.Interop
|
||||
(
|
||||
SafeFileHandle device,
|
||||
IOControlCode ioControlCode,
|
||||
[MarshalAs(UnmanagedType.AsAny)] [In] object inBuffer,
|
||||
[MarshalAs(UnmanagedType.AsAny)][In] object inBuffer,
|
||||
uint inBufferSize,
|
||||
[MarshalAs(UnmanagedType.AsAny)] [Out] object outBuffer,
|
||||
[MarshalAs(UnmanagedType.AsAny)][Out] object outBuffer,
|
||||
uint nOutBufferSize,
|
||||
out uint bytesReturned,
|
||||
IntPtr overlapped);
|
||||
|
||||
Reference in New Issue
Block a user