Recent

Author Topic: Battery status notification  (Read 9963 times)

sin_dragan

  • Full Member
  • ***
  • Posts: 127
Battery status notification
« on: September 19, 2013, 08:53:43 am »
Hi, I'm writing a application for WinCE 5 and 6 platform. I ve included battery meter, and using device DLL function to get battery status (function GetSystemPowerStatusEx is also performing good) and I m using Timer to call the function.

To avoid this I want to intercept a system message or receive a notification from system that the battery info changed and then update the meter on application.

Below is the text I found, but it's related to .NET platform.

I found this text regarding this problem:

http://english.tebyan.net/newindex.aspx?pid=31159&BookID=23937&PageIndex=125&Language=3

Can you tell me which message I should intercept so that I can get notified of system power change?

I see that the coredll.dll has some notification functions, but I'm not sure it's the right direction.

Thank you





Power Notifications

One of the more welcome features of the Power Manager is its ability to notify an application when the power state of the system changes. This ability frees the application from polling the battery state manually to monitor the power. An application can request that the Power Manager send a notification to the application when the power state of the system changes by calling RequestPowerNotifications. The Power Manager then sends the notifications through a message queue that has been previously created by the application.

RequestPowerNotifications is prototyped as

HANDLE RequestPowerNotifications (HANDLE hMsgQ, DWORD Flags);

The first parameter is the handle to a message queue that the application has previously created. The second parameter is a series of flags indicating which notifications the application wants to receive. The flags, which can be ORed together, are as follows:

PBT_TRANSITION Receive notifications when the power state changes—for example, when the system goes from On to Suspend.

PBT_RESUME Receive notifications when the system resumes.

PBT_POWERSTATUSCHANGEReceive notifications when the system transitions between AC and battery power.

PBT_POWERINFOCHANGE Receive notifications when the power information, such as the battery level, changes.

POWER_NOTIFY_ALL Receive all power notifications.


Windows 7 64 bit
Lazarus 1.4.1 (w/fixes) FPC 2.6.4 win32

bambamns

  • Full Member
  • ***
  • Posts: 223
Re: Battery status notification
« Reply #1 on: September 27, 2013, 09:48:53 pm »
Lazarus 1.8.4 + FPC 2.6.4 x86 (rebuild) and Lazarus 2.0, Windows 7 x64, unless otherwise specified

swierzbicki

  • Full Member
  • ***
  • Posts: 177
Re: Battery status notification
« Reply #2 on: October 02, 2013, 11:37:59 am »
@Bambams,

I'm jumping into this topic :) (I want to detect when my device come out of suspend mode.)

I'm trying to convert this structure  :

Code: [Select]
  typedef MSGQUEUEOPTIONS_OS{
    DWORD dwSize;
    DWORD dwFlags;
    DWORD dwMaxMessages;
    DWORD cbMaxMessage;
    BOOL bReadAccess;
  } MSGQUEUEOPTIONS, FAR* LPMSGQUEUEOPTIONS, *PMSGQUEUEOPTIONS; 
   

to Lazarus :

 
Code: [Select]
MSGQUEUEOPTIONS = record
    dwSize : DWORD;
    dwFlags : DWORD ;
    dwMaxMessages : DWORD ;
    cbMaxMessage : DWORD;
    bReadAccess : BOOL;
  end;
  PMSGQUEUEOPTIONS=^MSGQUEUEOPTIONS; 


Is this correct ?

The next step will be the notification queue creation (guess it will be harder for a noob like me)

Thanx
Lazarus 1.6.2
fpc 3.0.0
wince/win32/win64
delphi berlin

bambamns

  • Full Member
  • ***
  • Posts: 223
Re: Battery status notification
« Reply #3 on: October 13, 2013, 05:53:27 am »
@swierzbicki,

Did you made it works ?

It seems to me that :
Code: [Select]
PMSGQUEUEOPTIONS=^MSGQUEUEOPTIONS;
has to be:
Code: [Select]
PMSGQUEUEOPTIONS=@MSGQUEUEOPTIONS;
My experience with WinCE is not to let them to go sleep.
I use two procedures to keep them in a suspend but not sleep mode:
Code: [Select]
procedure SystemIdleTimerReset; stdcall; external 'coredll.dll';
procedure SHIdleTimerReset; stdcall; external 'aygshell.dll' name 'SHIdleTimerReset';         
Just call them every 15 sec and it will be ok.
Lazarus 1.8.4 + FPC 2.6.4 x86 (rebuild) and Lazarus 2.0, Windows 7 x64, unless otherwise specified

chrgra

  • Jr. Member
  • **
  • Posts: 69
Re: Battery status notification
« Reply #4 on: June 01, 2014, 03:56:27 am »
I think this will do the trick.....


unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  Windows, msgqueue, pm;

type

TMyThread = class(TThread)
private
  fStatusText: string;
  mHandle : Handle;
  pHandle : Handle;
  mOptions : MSGQUEUEOPTIONS;
  mBroadcast : POWER_BROADCAST;
  nBytesRead : dword;
  dwFlags    : dWord;
  counter : integer;
  procedure ShowStatus;
protected
  procedure Execute; override;
public
  constructor Create(CreateSuspended: boolean);
end;


  { TForm1 }

  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

function RequestPowerNotifications(hMsgQ : HANDLE; flags : DWORD) : HANDLE; external kerneldll name 'RequestPowerNotifications';
function StoppowerNotifications(hMsgQ : HANDLE) : HANDLE; external kerneldll name 'StopPowerNotifications';

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
var
  MyThread : TMyThread;
begin
  MyThread := TMyThread.Create(True); // With the True parameter it doesn't start automatically
  if Assigned(MyThread.FatalException) then
    raise MyThread.FatalException;
  memo1.Clear;
  // Here the code initialises anything required before the threads starts executing

  MyThread.Start;

end;

procedure TMyThread.ShowStatus;
// this method is only called by Synchronize(@ShowStatus) and therefore
// executed by the main thread
// The main thread can access GUI elements, for example Form1.Caption.
begin
  form1.Memo1.Append(inttostr(counter) + ' ' + fstatustext);
end;



procedure TMyThread.Execute;
var
  newStatus : string;
begin
  fStatusText := 'TMyThread Starting ...';
  Synchronize(@Showstatus);
  fStatusText := 'TMyThread Running ...';
  while (not Terminated) and (true {any condition required}) do
  begin
     inc(counter);
     Synchronize(@Showstatus);
     fstatustext := '';
     //sleep(500);
 {    function ReadMsgQueue(hMsgQ:HANDLE;
                      lpBuffer:LPVOID;
                      cbBufferSize:DWORD;
                      lpNumberOfBytesRead:LPDWORD;
                      dwTimeout:DWORD;
                      pdwFlags:LPDWORD):BOOL; external KernelDLL name 'ReadMsgQueue'; // index 112

 }

     if (not ReadMsgQueue(mHandle,@mBroadcast, sizeof(mBroadcast),  @nBytesRead,50000,@dwFlags) ) then
     begin
        fstatustext := inttostr(nbytesread) + ' '+ syserrormessage(GetLastError);
       // Synchronize(@Showstatus);
     end;
     case mBroadcast._Message of
       PBT_RESUME : fstatustext := 'PBT_RESUME';
       PBT_POWERSTATUSCHANGE : fstatustext := 'PBT_POWERSTATUSCHANGE';
       PBT_POWERINFOCHANGE: fstatustext := 'PBT_POWERINFOCHANGE';
       PBT_TRANSITION: fstatustext := 'PBT_TRANSITION';
     end;
                                               {    RETAILMSG(1, (TEXT("PBT_TRANSITION")));
                                                                                switch( POWER_STATE(pwrStatus.Flags) )
                                                                                {
                                                                                                case POWER_STATE_ON:
                                                                                                                RETAILMSG(1, (TEXT(" POWER_STATE_ON\n")));
                                                                                                                break;
                                                                                                case POWER_STATE_OFF:
                                                                                                                RETAILMSG(1, (TEXT(" POWER_STATE_OFF\n")));
                                                                                                                break;
                                                                                                case POWER_STATE_CRITICAL:
                                                                                                                RETAILMSG(1, (TEXT(" POWER_STATE_CRITICAL\n")));
                                                                                                                break;
                                                                                                case POWER_STATE_BOOT:
                                                                                                                RETAILMSG(1, (TEXT(" POWER_STATE_BOOT\n")));
                                                                                                                break;
                                                                                                case POWER_STATE_IDLE:
                                                                                                                RETAILMSG(1, (TEXT(" POWER_STATE_IDLE\n")));
                                                                                                                break;
                                                                                                case POWER_STATE_SUSPEND:
                                                                                                                RETAILMSG(1, (TEXT(" POWER_STATE_SUSPEND\n")));
                                                                                                                break;
                                                                                                case POWER_STATE_RESET:
                                                                                                                RETAILMSG(1, (TEXT(" POWER_STATE_RESET\n")));
                                                                                                                break;
                                                                                                default:
                                                                                                                break;
                                                                                }
                                                                                break;

                                                                default:
                                                                                break;



   }
   end;
   StopPowerNotifications(mHandle);
   CloseMsgQueue(mHandle);
end;


constructor TMyThread.Create(CreateSuspended: boolean);
begin
   counter := 0;
   mHandle := 0;
   pHandle := 0;
   mOptions.bReadAccess:=true;
   mOptions.cbMaxMessage:=sizeof(mBroadcast);
   mOptions.dwSize:=5*sizeof(mBroadcast);
   mOptions.dwMaxMessages:=5;
   mOptions.dwFlags:=  MSGQUEUE_ALLOW_BROKEN;



   FreeOnTerminate := True;
   mHandle := CreateMsgQueue('powernotify',@mOptions);
  // showmessage('na createmsgqueue '+syserrormessage(getlasterror));
   if mHandle = 0 then
   begin
      showmessage('newmsgqueue failed');
     // terminated := true;
   end;
   pHandle := requestpowernotifications(mHandle,POWER_NOTIFY_ALL);
  // showmessage('na requestpowernotifications '+syserrormessage(getlasterror));
   if (pHandle = 0) then
   begin
      showmessage('powernotification failed');
     // terminated := true;
   end;
   inherited Create(CreateSuspended);
end;




end.

vincococka

  • Full Member
  • ***
  • Posts: 101
Re: Battery status notification
« Reply #5 on: February 14, 2015, 05:34:35 pm »
@chrgra: thanks a lot for your code snipped. It helped really a lot these days when I needed WinCE power management notifications. KUDOZ!
---
  Guide me God and I`ll find you