Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

AC/Battery status


  • Please log in to reply
8 replies to this topic
antonyb
  • Members
  • 61 posts
  • Last active: Mar 07 2006 09:24 AM
  • Joined: 26 May 2004
I seem to remember someone asking for this ages ago. I've been using it for a while, but just forgot to post it.

Get the power status of your PC - really only useful for laptops. Return values are documented here. Makes heavy use of shimanov's ReadInteger function.

Ant.



VarSetCapacity(powerstatus, 1+1+1+1+4+4)
success := DllCall("kernel32.dll\GetSystemPowerStatus", "uint", &powerstatus)

acLineStatus:=ReadInteger(&powerstatus,0,1,false)
batteryFlag:=ReadInteger(&powerstatus,1,1,false)
batteryLifePercent:=ReadInteger(&powerstatus,2,1,false)
batteryLifeTime:=ReadInteger(&powerstatus,4,4,false)
batteryFullLifeTime:=ReadInteger(&powerstatus,8,4,false)

output=AC Status: %acLineStatus%`nBattery Flag: %batteryFlag%`nBattery Life (percent): %batteryLifePercent%`nBattery Life (time): %batteryLifeTime%`nBattery Life (full time): %batteryFullLifeTime%
MsgBox, %output%


ReadInteger( p_address, p_offset, p_size, p_hex=true )
{
  value = 0
  old_FormatInteger := a_FormatInteger
  if ( p_hex )
    SetFormat, integer, hex
  else
    SetFormat, integer, dec
  loop, %p_size%
    value := value+( *( ( p_address+p_offset )+( a_Index-1 ) ) << ( 8* ( a_Index-1 ) ) )
  SetFormat, integer, %old_FormatInteger%
  return, value
}


toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005
to make it more/easier readable, you may use
output=

  (LTrim

    AC Status: %acLineStatus%

    Battery Flag: %batteryFlag%

    Battery Life (percent): %batteryLifePercent%

    Battery Life (time): %batteryLifeTime%

    Battery Life (full time): %batteryFullLifeTime%

  )
Thanks for the script. I may use it, since I own a laptop.
Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

ladiko
  • Members
  • 290 posts
  • Last active: Jan 16 2012 11:46 PM
  • Joined: 13 Jul 2006
how to interpret the data?

what is battery flag?

what is the difference between battery time and battery full time

my output is:
AC Status: 0
Battery Flag: 0
Battery Life (percent): 42
Battery Life (time): 5572
Battery Life (full time): 4294967295

i'm on battery and have 42% - thats ok - but what are the other ones?

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005
GetSystemPowerStatus just fills in a SYSTEM_POWER_STATUS structure.
typedef struct _SYSTEM_POWER_STATUS {
  BYTE ACLineStatus;
  BYTE BatteryFlag;
  BYTE BatteryLifePercent;
  BYTE Reserved1;
  DWORD BatteryLifeTime;
  DWORD BatteryFullLifeTime;
} SYSTEM_POWER_STATUS, 
 *LPSYSTEM_POWER_STATUS;

ACLineStatus
. . The AC power status. This member can be one of the following values.
. . Value Meaning
. . 0 Offline
. . 1 Online
. . 255 Unknown status
BatteryFlag
. . The battery charge status. This member can contain one or more of the following flags.
. . Value Meaning
. . 1 High—the battery capacity is at more than 66 percent
. . 2 Low—the battery capacity is at less than 33 percent
. . 4 Critical—the battery capacity is at less than five percent
. . 8 Charging
. . 128 No system battery
. . 255 Unknown status—unable to read the battery flag information

. . The value is zero if the battery is not being charged and the battery capacity is between low and high.
BatteryLifePercent
. . The percentage of full battery charge remaining. This member can be a value in the range 0 to 100, or 255 if status is unknown.
Reserved1
. . Reserved; must be zero.
BatteryLifeTime
. . The number of seconds of battery life remaining, or –1 if remaining seconds are unknown.
BatteryFullLifeTime
. . The number of seconds of battery life when at full charge, or –1 if full battery lifetime is unknown.

Remarks

The system is only capable of estimating BatteryFullLifeTime based on calculations on BatteryLifeTime and BatteryLifePercent. Without smart battery subsystems, this value may not be accurate enough to be useful.

4294967295 is actually -1 (script has read UInt instead of Int), this script could be improved slightly to give clearer info, indeed. :-) But obviously, it is just a quick hack / proof of concept / starting point for better interface.
Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005
;~ Goto Test



VarSetCapacity(powerStatus, 1+1+1+1+4+4)

success := DllCall("GetSystemPowerStatus", "UInt", &powerStatus)

If (ErrorLevel != 0 OR success = 0)

{

	MsgBox 16, Power Status, Can't get the power status...

	ExitApp

}

acLineStatus := GetInteger(powerStatus, 0, false, 1)

batteryFlag := GetInteger(powerStatus, 1, false, 1)

batteryLifePercent := GetInteger(powerStatus, 2, false, 1)

batteryLifeTime := GetInteger(powerStatus, 4, true)

batteryFullLifeTime := GetInteger(powerStatus, 8, true)



If acLineStatus = 0

	acLineStatus = Offline

Else If acLineStatus = 1

	acLineStatus = Online

Else If acLineStatus = 255

	acLineStatus = Unknown



If batteryFlag = 0

	batteryFlag = Not being charged - Between 33 and 66 percent

Else If batteryFlag = 1

	batteryFlag =  High - More than 66 percent

Else If batteryFlag = 2

	batteryFlag = Low - Less than 33 percent

Else If batteryFlag = 4

	batteryFlag = Critical - Less than 5 percent

Else If batteryFlag = 8

	batteryFlag = Charging

Else If batteryFlag = 128

	batteryFlag = No system battery

Else If batteryFlag = 255

	batteryFlag = Unknown



If batteryLifePercent = 255

	batteryLifePercent = Unknown

Else

	batteryLifePercent = %batteryLifePercent%`%



If batteryLifeTime = -1

	batteryLifeTime = Unknown

Else

	batteryLifeTime := GetFormatedTime(batteryLifeTime)



If batteryFullLifeTime = -1

	batteryFullLifeTime = Unknown

Else

	batteryFullLifeTime := GetFormatedTime(batteryFullLifeTime)



output =

(

AC Status: %acLineStatus%

Battery state and capacity: %batteryFlag%

Battery Life: %batteryLifePercent%

Remaining Battery Life: %batteryLifeTime%

Full Battery Life: %batteryFullLifeTime%

)

MsgBox 64, Power Status, %output%



Return



GetInteger(ByRef @source, _offset = 0, _bIsSigned = false, _size = 4)

{

	local result



	Loop %_size%  ; Build the integer by adding up its bytes.

	{

		result += *(&@source + _offset + A_Index-1) << 8*(A_Index-1)

	}

	If (!_bIsSigned OR _size > 4 OR result < 0x80000000)

		Return result  ; Signed vs. unsigned doesn't matter in these cases.

	; Otherwise, convert the value (now known to be 32-bit & negative) to its signed counterpart:

	return -(0xFFFFFFFF - result + 1)

}



GetFormatedTime(_seconds)

{

	local h, m, s, t



	h := _seconds // 3600

	_seconds -= h * 3600

	m := _seconds // 60

	s := _seconds - m * 60

	If (h > 1)

		t := h . " hours"

	Else IF (h = 1)

		t := "1 hour"

	If (t != "" and m + s > 0)

		t := t . " "

	If (m > 1)

		t := t . m . " minutes"

	Else If (m = 1)

		t := t . "1 minute"

	If (t != "" and s > 0)

		t := t . " "

	If (s > 1)

		t := t . s . " seconds"

	Else If (s = 1)

		t := t . "1 second"

	Else If (t = "")

		t := "0 seconds"



	Return t

}



Test:



MsgBox %

( Join

 GetFormatedTime(10000) . "`n" .

 GetFormatedTime(3661) . "`n" .

 GetFormatedTime(1000) . "`n" .

 GetFormatedTime(100) . "`n" .

 GetFormatedTime(10) . "`n" .

 GetFormatedTime(1) . "`n" .

 GetFormatedTime(0) . "`n" .

 ""

)


Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")

ladiko
  • Members
  • 290 posts
  • Last active: Jan 16 2012 11:46 PM
  • Joined: 13 Jul 2006
i wanna repeat the call every 2 seconds to detect if power source change, so is there a part of the subroutine that should only be executed once so that it is outside of the loop?

for example VarSetCapacity(powerStatus, 1+1+1+1+4+4) ?

SetTimer, GetPowerSource, 2000
return ; End of main program

GetPowerSource:
	VarSetCapacity(powerStatus, 1+1+1+1+4+4)
	success := DllCall("GetSystemPowerStatus", "UInt", &powerStatus)
	If (ErrorLevel != 0 OR success = 0)
	{
		MsgBox 16, Power Status, Can't get the power status...
		ExitApp
	}
	acLineStatus := GetInteger(powerStatus, 0, false, 1)

	If acLineStatus = 0
		acLineStatus = Offline
	
	MsgBox 64, Power Source, Power Source: %acLineStatus%
Return


PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005
Indeed, even if I think it doesn't hurt to be in the loop...
You probably want to set a prevACLineStatus variable, to compare two successive values.
Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")

Cragaha
  • Members
  • 265 posts
  • Last active: Jan 04 2016 02:24 AM
  • Joined: 19 Nov 2010
Thanks to Emmanuel, Thanh00, tic and ofcourse antonyb
Here is what I made out of it..

Posted Image

LazyMan
  • Members
  • 587 posts
  • Last active: Oct 21 2014 05:13 PM
  • Joined: 17 Feb 2011
Thanks for this. :D