Home | Kontakt | Sitemap

Start

Über mich

Kontakt

Sitemap

Lizenz

Anleitungen

DVD, miniDVD

SVCD

Audio, Audio-CD (CD-DA)

AVI

Software

Von Freunden und Bekannten

Eigene Programme

Programmierung

Delphi

Lazarus

Delphi/Lazarus

Projekte

MPEG-1/2 Video

Optische Laufwerke

Audio-CD (CDDA)

Raspberry Pi Dashcam

Verschiedenes

MPEG 2 Schnitt

Project X

VCD Easy

Hardlinks

Windows

Links

Software

Programmierung Delphi - Batterie - Informationen zur Batterie abfragen

Informationen zur Batterie abfragen

Beschreibung

Mit dem Controlcode IOCTL_BATTERY_QUERY_INFORMATION erhält man verschiedene Informationen der Batteris, zum Beispiel Bezeichnung, Hersteller und Seriennummer.

Control Code IOCTL_BATTERY_QUERY_INFORMATION

Die c++-Definition im NSDN Windows Dev Center:

BOOL DeviceIoControl(
  (HANDLE) hDevice,                // handle to battery
  IOCTL_BATTERY_QUERY_INFORMATION, // dwIoControlCode
  (LPVOID) lpInBuffer,             // input buffer
  (DWORD) nInBufferSize,           // size of input buffer
  (LPVOID) lpOutBuffer,            // output buffer
  (DWORD) nOutBufferSize,          // size of output buffer
  (LPDWORD) lpBytesReturned,       // number of bytes returned
  (LPOVERLAPPED) lpOverlapped      // OVERLAPPED structure
);

hDevice: Das Handle, welches im Kapitel Handle ermittelt wurde.

dwIoControlCode: Der Controlcode für die Operation.

lpInBuffer: Ein Zeiger auf den Speicher mit einer Datenstuktur BATTERY_QUERY_INFORMATION, mit welcher mitgeteilt wird, welche Information man möchte.

nInBufferSize: Die Größe der Datenstruktur in Byte.

lpOutBuffer: Der Zeiger auf den Rückgabepuffer. Der Datentyp und die Größe sind vom angeforderten Informationlevel abhängig.

nOutBufferSize: Die Größe des Rückgabepuffers. Sie ist vom Informationslevel abhängig.

lpBytesReturned: Ein Zeiger auf einen Wert, der angibt, wieviel Daten zurückgegben wurden. War der Rückgabepuffer zu klein ist der Wert 0 und GetLastError gibt den Fehlerwert ERROR_INSUFFICIENT_BUFFER zurück. Wenn die Overlapped Struktur nicht verwendet wird, darf dieser nicht 0 sein.

lpOverlapped: Ein Zeiger auf die Overlapped Struktur. Sie kann nur vorhanden sein, wenn das Gerät mit dem Flag FILE_FLAG_OVERLAPPED geöffnet wurde. Dies ist hier nicht der Fall.

Wurde die Operation fehlerfrei durchgeführt ist der Rückgabewert 0.

Die Funktion ist in Delphi in der Unit Windows deklariert.

Der Controlcode IOCTL_BATTERY_QUERY_INFORMATION ist in der batclass.h definiert:

#define FILE_DEVICE_BATTERY   0x00000029
 
#define IOCTL_BATTERY_QUERY_INFORMATION \
    CTL_CODE(FILE_DEVICE_BATTERY,0x11,METHOD_BUFFERED,FILE_READ_ACCESS)
const
  FILE_DEVICE_BATTERY = $00000029;
  FILE_READ_ACCESS    = $0001;
  METHOD_BUFFERED     = $0000;
 
const
  IOCTL_BATTERY_QUERY_INFORMATION = (FILE_DEVICE_BATTERY shl 16 or
                                     FILE_READ_ACCESS shl 14 or
                                     $11 shl 2 or
                                     METHOD_BUFFERED);

Struktur BATTERY_QUERY_INFORMATION

Die Struktur enthält die Batterieinformationen und die c++-Definition im NSDN Windows Dev Center lautet:

typedef struct _BATTERY_QUERY_INFORMATION {
  ULONG                           BatteryTag;
  BATTERY_QUERY_INFORMATION_LEVEL InformationLevel;
  LONG                            AtRate;
} BATTERY_QUERY_INFORMATION, *PBATTERY_QUERY_INFORMATION;

BatteryTag: Der aktuelle Batterie-Tag für die Batterie, welcher im Kapitel Tag ermittelt wurde. Wenn dieser Wert nicht mit dem aktuellen Tag der Batterie übereinstimmt, wird die Anfrage mit ERROR_FILE_NOT_FOUND abgeschlossen.

InformationLevel: Gibt an, welche Information gewünscht wird.

Informationslevel Wert Beschreibung
BatteryDeviceName 4 Nulltermierter Unicodestring mit dem Namen der Batterie.
BatteryEstimatedTime 3 Die geschätzte Akkulaufzeit in Sekunden als ULONG. Bei Änderungen wird es keine Benachrichtigung. Wenn die Zeit unbekannt ist (zB. wenn die Batterie nicht entladen wird), ist der Rückgabewert BATTERY_UNKNOWN_TIME.
BatteryGranularityInformation 1 Ein Array von BATTERY_REPORTING_SCALE-Strukturen mit maximal vier Einträgen.
BatteryInformation 0 Eine BATTERY_INFORMATION Struktur.
BatteryManufactureDate 5 Eine BATTERY_MANUFACTURE_DATE Struktur.
BatteryManufactureName 6 Ein nullterminierter Unicodestring mit dem Namen des Herstellers.
BatterySerialNumber 8 Ein nullterminierter Unicodestring mit der Seriennummer.
BatteryTemperature 2 Ein ULONG-Wert, welcher die gegenwärtige Temperatur in Zehntel Grad Kelvin angibt.
BatteryUniqueID 7 Ein nullterminierter Unicodestring für eine eindeutige Identifizierung.

AtRate: Dieser Parameter wird nur im Zusammenhang mit BatteryEstimatedTime verwendet. Ist der Parameter Null basiert die Berechnung der Zeit auf der aktuellen Abflussrate. Sonst wurde die zurückgegebene Zeit für die angegebene Rate berechnet.

Die Deklaration in Delphi:

type
  BATTERY_QUERY_INFORMATION_LEVEL =
  (
    BatteryInformation,
    BatteryGranularityInformation,
    BatteryTemperature,
    BatteryEstimatedTime,
    BatteryDeviceName,
    BatteryManufactureDate,
    BatteryManufactureName,
    BatteryUniqueID,
    BatterySerialNumber
  );
  TBATTERY_QUERY_INFORMATION_LEVEL = BATTERY_QUERY_INFORMATION_LEVEL;
 
type
  _BATTERY_QUERY_INFORMATION =
  record
    BatteryTag       : ULONG;
    InformationLevel : BATTERY_QUERY_INFORMATION_LEVEL;
    AtRate           : LongInt;
  end;
  TBATTERY_QUERY_INFORMATION = _BATTERY_QUERY_INFORMATION;
  PBATTERY_QUERY_INFORMATION = ^_BATTERY_QUERY_INFORMATION;

Struktur BATTERY_REPORTING_SCALE

typedef struct {
  ULONG Granularity;
  ULONG Capacity;
} BATTERY_REPORTING_SCALE, *PBATTERY_REPORTING_SCALE;

Granularity: Die Auflösung des Kapazitätswertes, der in Milliwattstunden (mWh) zurückgegeben wird. Sie kann sich im Laufe der Zeit ändern, da Batterieentladung und Wiederaufladung den Messbereich verändern.

Capacity: Die obere Kapazitätsgrenze für die Auflösung. Die Auflösung gilt für die von IOCTL_BATTERY_QUERY_STATUS gemeldeten Kapazitäten, die kleiner oder gleich dieser Kapazität (mWh) sind, aber größer oder gleich der im vorherigen Arrayelement angegebenen Kapazität oder null, wenn dies das erste Arrayelement ist.

Die Deklaration in Delphi:

type
  BATTERY_REPORTING_SCALE =
  record
    Granularity : ULONG;
    Capacity    : ULONG;
  end;
  TBATTERY_REPORTING_SCALE = BATTERY_REPORTING_SCALE;
  PBATTERY_REPORTING_SCALE = ^BATTERY_REPORTING_SCALE;
 
  TBATTERY_REPORTING_SCALE_ARRAY = array[0..3] of TBATTERY_REPORTING_SCALE;

Struktur BATTERY_INFORMATION

Die Struktur enthält verschiedene Informationen über die Batterie.

typedef struct _BATTERY_INFORMATION {
  ULONG Capabilities;
  UCHAR Technology;
  UCHAR Reserved[3];
  UCHAR Chemistry[4];
  ULONG DesignedCapacity;
  ULONG FullChargedCapacity;
  ULONG DefaultAlert1;
  ULONG DefaultAlert2;
  ULONG CriticalBias;
  ULONG CycleCount;
} BATTERY_INFORMATION, *PBATTERY_INFORMATION;

Capabilities: Die Kapazitäten der Batterie. In dem Parameter können mehrere Flags gesetzt sein:

Konstante Beschreibung
BATTERY_CAPACITY_RELATIVE
0x40000000
Wenn dieses Bit nicht gesetzt ist, ist die Kapazität in Milliwattstunden (mWh) und die Rate in Milliwatt (mW) angegeben. Ist es gesetzt, wird in Einheiten pro Stunde gemeldet. Bei einer voll aufgeladene Kapazität von 100 gibt eine Rate von 200 an, dass die Batterie in einer halben Stunde leer ist.
BATTERY_IS_SHORT_TERM
0x20000000
Zeigt an, dass dies der normale Betrieb für eine fehlersichere Funktion ist. Wenn dieses Bit nicht gesetzt ist, wird erwartet, dass die Batterie während des normalen Systemgebrauchs verwendet wird.
BATTERY_SET_CHARGE_SUPPORTED
0x00000001
Gibt an, dass die eingestellten Informationsanforderungen des Typs BatteryCharge von diesem Akku unterstützt werden.
BATTERY_SET_DISCHARGE_SUPPORTED
0x00000002
Zeigt an, dass die eingestellten Informationsanforderungen des Typs BatteryDischarge von diesem Akku unterstützt werden.
BATTERY_SYSTEM_BATTERY
0x80000000
Zeigt an, dass die Batterie die allgemeine Stromversorgung des Systems übernehmen kann.

Technology: Der Wert 0 gibt an, dass die Batterie nicht wiederaufladbar ist. Der Wert 1 gibt an, dass die Batterie wiederauflladbar ist.

Chemistry: Enthält einen Unicodestring mit der Abkürzung für die Batteriechemie.

StringBedeutung
PbAcLead Acid
LIONLithium Ion
Li-ILithium Ion
NiCdNickel Cadmium
NiMHNickel Metal Hydride
NiZnNickel Zinc
RAMRechargeable Alkaline-Manganese

Wenn BATTERY_CAPACITY_RELATIVE nicht gesetzt ist, sind die Kapazitäten in mWh angegeben. Sonst sind es relative Angaben.

DesignedCapacity: Die theoretische Kapazität der neuen Batterie.

FullChargedCapacity: Die Kapazität des voll geladenen Akkus. Im Vergleich mit DesignedCapacity kann man den Verschleiß der Batterie schätzen.

DefaultAlert1: Die vom Hersteller vorgeschlagene Kapazität in mWh, bei der ein geringer Batteriealarm auftreten sollte. Die Definitionen von niedrig variieren von Hersteller zu Hersteller. Dieser Wert wird üblicherweise als Standardeinstellung für den kritischen Batteriealarm verwendet.

DefaultAlert2: Die vom Hersteller vorgeschlagene Kapazität in mWh, bei der eine Warnmeldung auftritt. Definitionen der Warnung variieren von Hersteller zu Hersteller. Dieser Wert wird üblicherweise als Standardeinstellung für den Batteriealarm verwendet.

CriticalBias: Die Abweichung von Null in mWh, welche auf Batterie Berichterstattung angewendet wird. Einige Batterien reservieren eine kleine Reserve, damit die Batterie nicht komplett entleert wird.

CycleCount: Die Anzahl der Lade-/Entladezyklen der Batterie, wenn die Batterie einen Zykluszähler unterstützt, sonst ist der Zähler 0.

Die Deklaration in Delphi:

type
  _BATTERY_INFORMATION =
  record
    Capabilities        : ULONG;
    Technology          : UCHAR;
    Reserved            : array [1..3] of UCHAR;
    Chemistry           : array [1..4] of UCHAR;
    DesignedCapacity    : ULONG;
    FullChargedCapacity : ULONG;
    DefaultAlert1       : ULONG;
    DefaultAlert2       : ULONG;
    CriticalBias        : ULONG;
    CycleCount          : ULONG;
  end;
  TBATTERY_INFORMATION = _BATTERY_INFORMATION;
  PBATTERY_INFORMATION = ^_BATTERY_INFORMATION;

Den Datentyp von Chemistry kann man auch mit CHAR deklarieren. Dann kann man sich später die Konvertierung von UCHAR = Byte nach CHAR sparen.

Struktur BATTERY_MANUFACTURE_DATE

Die Struktur enthält das Datum der Herstellung der Batterie.

typedef struct _BATTERY_MANUFACTURE_DATE {
  UCHAR  Day;
  UCHAR  Month;
  USHORT Year;
} BATTERY_MANUFACTURE_DATE, *PBATTERY_MANUFACTURE_DATE;

Day: Der Tag eines Monats im Bereich von 1 bis 31.

Month: Der Monat eines Jahres im Bereich von 1 bis 12.

Year: Ein Jahr im Bereich von 1900 bis 2100.

Die Deklaration in Delphi:

type
  _BATTERY_MANUFACTURE_DATE =
  record
    Day   : UCHAR;
    Month : UCHAR;
    Year  : Word;
  end;
  TBATTERY_MANUFACTURE_DATE = _BATTERY_MANUFACTURE_DATE;
  PBATTERY_MANUFACTURE_DATE = ^_BATTERY_MANUFACTURE_DATE;

Funktion in Delphi 7

Bei den Informationslevel BatteryDeviceName, BatteryManufactureName, BatterySerialNumber und BatteryUniqueID gibt es als Ergebnis nullterminierte Unicodestrings. Die Funktionen sind damit fast identisch.

function GetBatteryManufactureName(hBattery: THandle; aTag: Cardinal): String;
var
  rBatQueryInfo  : TBATTERY_QUERY_INFORMATION;
  pOutBuffer     : PWideChar;
  nOutBufferSize : Cardinal;
  dwReturned     : Cardinal;
begin
  Result := rsError;
 
  ZeroMemory(@rBatQueryInfo, SizeOf(TBATTERY_QUERY_INFORMATION));
  rBatQueryInfo.BatteryTag       := aTag;
  rBatQueryInfo.InformationLevel := BatteryManufactureName;
  rBatQueryInfo.AtRate           := 0;
 
  nOutBufferSize := 255;
  pOutBuffer     := AllocMem(nOutBufferSize);
 
  dwReturned := 0;
 
  if (DeviceIoControl(hBattery,
                      IOCTL_BATTERY_QUERY_INFORMATION,
                      @rBatQueryInfo,
                      SizeOf(TBATTERY_QUERY_INFORMATION),
                      pOutBuffer,
                      nOutBufferSize,
                      dwReturned,
                      nil))
  then Result := WideCharToString(pOutBuffer);
 
  FreeMem(pOutBuffer);
end;

Obwohl alle drei Elemente von rBatQueryInfo gesetzt werden ist das ZeroMemry notwendig. Sonst gibt es den Systemfehler ERROR_INVALID_FUNCTION - 1 (0x1) - Incorrect function.

Bei BatteryEstimatedTime erhält man eine Zeit in Sekunden als ULONG. Ist die Zeit unbekannt, ist der Wert $80000000 (BATTERY_UNKNOWN_TIME). Undokumentiert ist der Wert DWORD(-1) = $FFFFFFFF. Dieser wird zurückgegeben, wenn die Batterie vollständig geladen ist.

function GetBatteryEstimatedTime(hBattery: THandle; aTag: Cardinal): String;
var
  rBatQueryInfo  : TBATTERY_QUERY_INFORMATION;
  pOutBuffer     : ULONG;
  nOutBufferSize : Cardinal;
  dwReturned     : Cardinal;
begin
  Result := rsError;
 
  ZeroMemory(@rBatQueryInfo, SizeOf(TBATTERY_QUERY_INFORMATION));
  rBatQueryInfo.BatteryTag       := aTag;
  rBatQueryInfo.InformationLevel := BatteryEstimatedTime;
  rBatQueryInfo.AtRate           := 0;
 
  nOutBufferSize := SizeOf(ULONG);
 
  dwReturned := 0;
 
  if (DeviceIoControl(hBattery,
                      IOCTL_BATTERY_QUERY_INFORMATION,
                      @rBatQueryInfo,
                      SizeOf(TBATTERY_QUERY_INFORMATION),
                      @pOutBuffer,
                      nOutBufferSize,
                      dwReturned,
                      nil))
  then begin
    case pOutBuffer of
      BATTERY_UNKNOWN_TIME : Result := rsUnknown;
      $FFFFFFFF            : Result := rsReady;
      else begin
        Result := rsClear;
        while (pOutBuffer > 0)
        do begin
          Result := IntToStr(pOutBuffer mod 60) + ':' + Result;
          pOutBuffer := pOutBuffer div 60;
        end;
        Delete(Result, Length(Result), 1);
      end;
    end;
  end;
end;

Für BatteryTemperature ist die Funktion ähnlich. Bei mir schlägt die Funktion mit dem Systemfehler ERROR_INVALID_FUNCTION - 1 (0x1) - Incorrect function. fehl. Da sie mit der Zeit funktioniert, denke ich, dass es daran liegt, dass kein Sensor vorhanden ist.

function GetBatteryTemperature(hBattery: THandle; aTag: Cardinal): String;
var
  rBatQueryInfo  : TBATTERY_QUERY_INFORMATION;
  pOutBuffer     : ULONG;
  nOutBufferSize : Cardinal;
  dwReturned     : Cardinal;
begin
  Result := rsError;
 
  ZeroMemory(@rBatQueryInfo, SizeOf(TBATTERY_QUERY_INFORMATION));
  rBatQueryInfo.BatteryTag       := aTag;
  rBatQueryInfo.InformationLevel := BatteryTemperature;
  rBatQueryInfo.AtRate           := 0;
 
  nOutBufferSize := SizeOf(ULONG);
 
  dwReturned := 0;
 
  if (DeviceIoControl(hBattery,
                      IOCTL_BATTERY_QUERY_INFORMATION,
                      @rBatQueryInfo,
                      SizeOf(TBATTERY_QUERY_INFORMATION),
                      @pOutBuffer,
                      nOutBufferSize,
                      dwReturned,
                      nil))
  then Result := Format('%d.%d Kelvin', [pOutBuffer div 10, pOutBuffer mod 10])
  else Result := rsNotSupported;
end;

Das Informationslevel BatteryManufactureDate scheint von meiner Laptop-Batterie ebenfalls nicht unterstützt zu werden. Denn die Funktion bringt nur den Systemfehler ERROR_INVALID_FUNCTION - 1 (0x1) - Incorrect function.

function GetBatteryManufactureDate(hBattery: THandle; aTag: Cardinal): String;
var
  rBatQueryInfo  : TBATTERY_QUERY_INFORMATION;
  pOutBuffer     : TBATTERY_MANUFACTURE_DATE;
  nOutBufferSize : Cardinal;
  dwReturned     : Cardinal;
begin
  Result := rsError;
 
  ZeroMemory(@rBatQueryInfo, SizeOf(TBATTERY_QUERY_INFORMATION));
  rBatQueryInfo.BatteryTag       := aTag;
  rBatQueryInfo.InformationLevel := BatteryManufactureDate;
  rBatQueryInfo.AtRate           := 0;
 
  nOutBufferSize := SizeOf(TBATTERY_MANUFACTURE_DATE);
 
  dwReturned := 0;
 
  if (DeviceIoControl(hBattery,
                      IOCTL_BATTERY_QUERY_INFORMATION,
                      @rBatQueryInfo,
                      SizeOf(TBATTERY_QUERY_INFORMATION),
                      @pOutBuffer,
                      nOutBufferSize,
                      dwReturned,
                      nil))
  then Result := Format('%.2d.%.2d.%.4d', [pOutBuffer.Day, pOutBuffer.Month, pOutBuffer.Year])
  else Result := rsNotSupported;
end;

Beim Informationslevel BatteryGranularityInformation bekommt man ein Array mit maximal vier Einträgen zurück. In einer Class sieht die Funktion sicher besser aus.

function GetBatteryGranularityInformation(hBattery: THandle; aTag: Cardinal;
                           out rBRSArray: TBATTERY_REPORTING_SCALE_ARRAY): Boolean;
var
  rBatQueryInfo : TBATTERY_QUERY_INFORMATION;
  dwReturned    : Cardinal;
begin
  ZeroMemory(@rBRSArray, SizeOf(TBATTERY_REPORTING_SCALE_ARRAY));
 
  ZeroMemory(@rBatQueryInfo, SizeOf(TBATTERY_QUERY_INFORMATION));
  rBatQueryInfo.BatteryTag       := aTag;
  rBatQueryInfo.InformationLevel := BatteryGranularityInformation;
  rBatQueryInfo.AtRate           := 0;
 
  dwReturned := 0;
 
  Result := (DeviceIoControl(hBattery,
                             IOCTL_BATTERY_QUERY_INFORMATION,
                             @rBatQueryInfo,
                             SizeOf(TBATTERY_QUERY_INFORMATION),
                             @rBRSArray,
                             SizeOf(TBATTERY_REPORTING_SCALE_ARRAY),
                             dwReturned,
                             nil));
end;

Das Informationslevel BatteryInformation liefert eine BATTERY_INFORMATION-Struktur. Diese wird erst abgeholt und dann ausgewertet.

function GetBatteryInformation(hBattery: THandle; aTag: Cardinal;
                                    out rBatInfo: TBATTERY_INFORMATION): Boolean;
var
  rBatQueryInfo : TBATTERY_QUERY_INFORMATION;
  dwReturned    : Cardinal;
begin
  ZeroMemory(@rBatInfo, SizeOf(TBATTERY_INFORMATION));
 
  ZeroMemory(@rBatQueryInfo, SizeOf(TBATTERY_QUERY_INFORMATION));
  rBatQueryInfo.BatteryTag       := aTag;
  rBatQueryInfo.InformationLevel := BatteryInformation;
  rBatQueryInfo.AtRate           := 0;
 
  dwReturned := 0;
 
  Result := (DeviceIoControl(hBattery,
                             IOCTL_BATTERY_QUERY_INFORMATION,
                             @rBatQueryInfo,
                             SizeOf(TBATTERY_QUERY_INFORMATION),
                             @rBatInfo,
                             SizeOf(TBATTERY_INFORMATION),
                             dwReturned,
                             nil));
end;

Download

Demo mit Delphi 7 compiliert
battery_info_exe.7z (155 kB) - MD5 (1kB)

Source der Demo
battery_info_src.7z (6 kB) - MD5 (1kB)

Tag > Informationen abfragen > Status