Jump to content


Photo

AC/Battery status


  • Please log in to reply
8 replies to this topic

#1 antonyb

antonyb
  • Members
  • 61 posts

Posted 26 January 2006 - 01:30 PM

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
}


#2 toralf

toralf
  • Fellows
  • 3948 posts

Posted 26 January 2006 - 01:42 PM

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.

#3 ladiko

ladiko
  • Members
  • 290 posts

Posted 23 October 2006 - 09:32 AM

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?

#4 PhiLho

PhiLho
  • Fellows
  • 6850 posts

Posted 23 October 2006 - 10:32 AM

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.

#5 PhiLho

PhiLho
  • Fellows
  • 6850 posts

Posted 23 October 2006 - 11:40 AM

;~ 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" .

 ""

)



#6 ladiko

ladiko
  • Members
  • 290 posts

Posted 23 October 2006 - 02:40 PM

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


#7 PhiLho

PhiLho
  • Fellows
  • 6850 posts

Posted 23 October 2006 - 02:47 PM

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.

#8 Nazzal

Nazzal
  • Members
  • 251 posts

Posted 27 October 2011 - 10:01 AM

Thanks to Emmanuel, Thanh00, tic and ofcourse antonyb
Here is what I made out of it..

Posted Image

#9 LazyMan

LazyMan
  • Members
  • 450 posts

Posted 16 January 2012 - 11:38 PM

Thanks for this. :D