AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

AC/Battery status

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
antonyb



Joined: 26 May 2004
Posts: 61

PostPosted: Thu Jan 26, 2006 2:30 pm    Post subject: AC/Battery status Reply with quote

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.



Code:
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
}
Back to top
View user's profile Send private message
toralf



Joined: 31 Jan 2005
Posts: 3842
Location: Bremen, Germany

PostPosted: Thu Jan 26, 2006 2:42 pm    Post subject: Reply with quote

to make it more/easier readable, you may use
Code:
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
Back to top
View user's profile Send private message Send e-mail Visit poster's website
ladiko



Joined: 14 Jul 2006
Posts: 190
Location: Berlin

PostPosted: Mon Oct 23, 2006 10:32 am    Post subject: Reply with quote

how to interpret the data?

what is battery flag?

what is the difference between battery time and battery full time

my output is:
Code:
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?
Back to top
View user's profile Send private message
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Mon Oct 23, 2006 11:32 am    Post subject: Reply with quote

GetSystemPowerStatus just fills in a SYSTEM_POWER_STATUS structure.
Code:
typedef struct _SYSTEM_POWER_STATUS {
  BYTE ACLineStatus;
  BYTE BatteryFlag;
  BYTE BatteryLifePercent;
  BYTE Reserved1;
  DWORD BatteryLifeTime;
  DWORD BatteryFullLifeTime;
} SYSTEM_POWER_STATUS,
 *LPSYSTEM_POWER_STATUS;
MSDN wrote:
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. Smile But obviously, it is just a quick hack / proof of concept / starting point for better interface.
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Mon Oct 23, 2006 12:40 pm    Post subject: Reply with quote

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

_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
ladiko



Joined: 14 Jul 2006
Posts: 190
Location: Berlin

PostPosted: Mon Oct 23, 2006 3:40 pm    Post subject: Reply with quote

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) ?

Code:
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
Back to top
View user's profile Send private message
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Mon Oct 23, 2006 3:47 pm    Post subject: Reply with quote

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.
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group