Skip to content

Commit 4a496d5

Browse files
committed
Fetch the current power consumption
1 parent 0873f27 commit 4a496d5

12 files changed

Lines changed: 226 additions & 0 deletions

File tree

BatteryMeter.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ static void BatteryMeter_updateValues(Meter* this) {
2828
BatteryInfo info = {
2929
.ac = AC_ERROR,
3030
.percent = NAN,
31+
.powerCurr = NAN,
3132
.energyCurr = NAN,
3233
.energyFull = NAN,
3334
};

BatteryMeter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ typedef struct BatteryInfo_ {
2222
ACPresence ac;
2323

2424
double percent; /* [0..100], NAN if unknown */
25+
double powerCurr; /* instantaneous power in W, NAN if unknown */
2526
double energyCurr; /* Wh, NAN if unknown */
2627
double energyFull; /* Wh, NAN if unknown */
2728
} BatteryInfo;

darwin/Platform.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ void Platform_getBattery(BatteryInfo* info) {
687687
*info = (BatteryInfo) {
688688
.ac = AC_ERROR,
689689
.percent = NAN,
690+
.powerCurr = NAN,
690691
.energyCurr = NAN,
691692
.energyFull = NAN,
692693
};
@@ -737,10 +738,22 @@ void Platform_getBattery(BatteryInfo* info) {
737738

738739
io_service_t batt = IOServiceGetMatchingService(iokit_port, IOServiceMatching("AppleSmartBattery"));
739740
if (batt) {
741+
CFNumberRef ampRef = IORegistryEntryCreateCFProperty(batt, CFSTR("Amperage"), kCFAllocatorDefault, 0);
740742
CFNumberRef voltRef = IORegistryEntryCreateCFProperty(batt, CFSTR("Voltage"), kCFAllocatorDefault, 0);
741743
CFNumberRef currCapRef = IORegistryEntryCreateCFProperty(batt, CFSTR("AppleRawCurrentCapacity"), kCFAllocatorDefault, 0);
742744
CFNumberRef maxCapRef = IORegistryEntryCreateCFProperty(batt, CFSTR("AppleRawMaxCapacity"), kCFAllocatorDefault, 0);
743745

746+
if (ampRef && voltRef) {
747+
double ampMA = 0.0;
748+
CFNumberGetValue(ampRef, kCFNumberDoubleType, &ampMA);
749+
750+
double voltMV = 0.0;
751+
CFNumberGetValue(voltRef, kCFNumberDoubleType, &voltMV);
752+
753+
// Follows the Smart Battery System (SBS) Standard
754+
info->powerCurr = ampMA * voltMV / -1e6;
755+
}
756+
744757
if (currCapRef && maxCapRef && voltRef) {
745758
double currMAh = 0.0;
746759
CFNumberGetValue(currCapRef, kCFNumberDoubleType, &currMAh);
@@ -764,6 +777,8 @@ void Platform_getBattery(BatteryInfo* info) {
764777
CFRelease(currCapRef);
765778
if (voltRef)
766779
CFRelease(voltRef);
780+
if (ampRef)
781+
CFRelease(ampRef);
767782

768783
IOObjectRelease(batt);
769784
}

dragonflybsd/Platform.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@ in the source distribution for its full text.
1212

1313
#include <devstat.h>
1414
#include <errno.h>
15+
#include <fcntl.h>
1516
#include <ifaddrs.h>
1617
#include <math.h>
1718
#include <time.h>
19+
#include <unistd.h>
20+
#include <dev/acpica/acpiio.h>
21+
#include <sys/ioctl.h>
1822
#include <sys/resource.h>
1923
#include <sys/socket.h>
2024
#include <sys/sysctl.h>
@@ -367,6 +371,7 @@ void Platform_getBattery(BatteryInfo* info) {
367371
*info = (BatteryInfo) {
368372
.ac = AC_ERROR,
369373
.percent = NAN,
374+
.powerCurr = NAN,
370375
.energyCurr = NAN,
371376
.energyFull = NAN,
372377
};
@@ -393,9 +398,11 @@ void Platform_getBattery(BatteryInfo* info) {
393398

394399
bool haveTotalRemain = false;
395400
bool haveTotalFull = false;
401+
bool haveTotalPower = false;
396402

397403
int64_t totalRemain = 0;
398404
int64_t totalFull = 0;
405+
int64_t totalPower = 0;
399406

400407
for (int u = 0; u < units; u++) {
401408
union acpi_battery_ioctl_arg bifArg = { .unit = u };
@@ -411,9 +418,11 @@ void Platform_getBattery(BatteryInfo* info) {
411418

412419
bool haveBatteryEnergyCurr = false;
413420
bool haveBatteryEnergyFull = false;
421+
bool haveBatteryPower = false;
414422

415423
int64_t batteryEnergyCurr = 0;
416424
int64_t batteryEnergyFull = 0;
425+
int64_t batteryPower = 0;
417426

418427
if (bif->lfcap != ACPI_BATT_UNKNOWN && bst->cap != ACPI_BATT_UNKNOWN) {
419428
if (bif->units == ACPI_BIF_UNITS_MW) {
@@ -439,6 +448,30 @@ void Platform_getBattery(BatteryInfo* info) {
439448
totalFull += batteryEnergyFull;
440449
haveTotalFull = true;
441450
}
451+
452+
if (bst->rate == ACPI_BATT_UNKNOWN)
453+
continue;
454+
455+
if (bif->units == ACPI_BIF_UNITS_MW) {
456+
batteryPower = (int64_t) bst->rate * 1000;
457+
haveBatteryPower = true;
458+
} else {
459+
uint32_t batteryVoltage = (bst->volt != ACPI_BATT_UNKNOWN) ? bst->volt : bif->dvol;
460+
461+
if (batteryVoltage != ACPI_BATT_UNKNOWN && batteryVoltage != 0) {
462+
batteryPower = (int64_t) bst->rate * batteryVoltage;
463+
haveBatteryPower = true;
464+
}
465+
}
466+
467+
if (!haveBatteryPower)
468+
continue;
469+
470+
if (bst->state & ACPI_BATT_STAT_DISCHARG)
471+
batteryPower = -batteryPower;
472+
473+
totalPower += batteryPower;
474+
haveTotalPower = true;
442475
}
443476

444477
close(fd);
@@ -451,4 +484,8 @@ void Platform_getBattery(BatteryInfo* info) {
451484
info->energyCurr = (double) totalRemain / 1000000.0;
452485
info->energyFull = (double) totalFull / 1000000.0;
453486
}
487+
488+
if (haveTotalPower) {
489+
info->powerCurr = (double) totalPower / 1000000.0;
490+
}
454491
}

freebsd/Platform.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ void Platform_getBattery(BatteryInfo* info) {
404404
*info = (BatteryInfo) {
405405
.ac = AC_ERROR,
406406
.percent = NAN,
407+
.powerCurr = NAN,
407408
.energyCurr = NAN,
408409
.energyFull = NAN,
409410
};
@@ -429,9 +430,11 @@ void Platform_getBattery(BatteryInfo* info) {
429430

430431
bool haveTotalRemain = false;
431432
bool haveTotalFull = false;
433+
bool haveTotalPower = false;
432434

433435
int64_t totalRemain = 0;
434436
int64_t totalFull = 0;
437+
int64_t totalPower = 0;
435438

436439
for (int u = 0; u < units; u++) {
437440
union acpi_battery_ioctl_arg bixArg = { .unit = u };
@@ -447,9 +450,11 @@ void Platform_getBattery(BatteryInfo* info) {
447450

448451
bool haveBatteryEnergyCurr = false;
449452
bool haveBatteryEnergyFull = false;
453+
bool haveBatteryPower = false;
450454

451455
int64_t batteryEnergyCurr = 0;
452456
int64_t batteryEnergyFull = 0;
457+
int64_t batteryPower = 0;
453458

454459
if (bix->lfcap != ACPI_BATT_UNKNOWN && bst->cap != ACPI_BATT_UNKNOWN) {
455460
if (bix->units == ACPI_BIX_UNITS_MW) {
@@ -474,6 +479,27 @@ void Platform_getBattery(BatteryInfo* info) {
474479
haveTotalRemain = true;
475480
haveTotalFull = true;
476481
}
482+
483+
if (bst->rate != ACPI_BATT_UNKNOWN && bst->rate > 0) {
484+
if (bix->units == ACPI_BIX_UNITS_MW) {
485+
batteryPower = (int64_t) bst->rate * 1000;
486+
haveBatteryPower = true;
487+
} else {
488+
uint32_t rateVoltage = (bst->volt != ACPI_BATT_UNKNOWN) ? bst->volt : bix->dvol;
489+
490+
if (rateVoltage != ACPI_BATT_UNKNOWN && rateVoltage != 0) {
491+
batteryPower = (int64_t) bst->rate * rateVoltage;
492+
haveBatteryPower = true;
493+
}
494+
}
495+
}
496+
497+
if (haveBatteryPower) {
498+
if (bst->state & ACPI_BATT_STAT_DISCHARG)
499+
batteryPower = -batteryPower;
500+
totalPower += batteryPower;
501+
haveTotalPower = true;
502+
}
477503
}
478504

479505
close(fd);
@@ -486,4 +512,8 @@ void Platform_getBattery(BatteryInfo* info) {
486512
info->energyCurr = (double) totalRemain / 1000000.0;
487513
info->energyFull = (double) totalFull / 1000000.0;
488514
}
515+
516+
if (haveTotalPower) {
517+
info->powerCurr = (double) totalPower / 1000000.0;
518+
}
489519
}

linux/Platform.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ static time_t Platform_Battery_cacheTime;
165165
static BatteryInfo Platform_Battery_cache = {
166166
.ac = AC_ERROR,
167167
.percent = NAN,
168+
.powerCurr = NAN,
168169
.energyCurr = NAN,
169170
.energyFull = NAN,
170171
};
@@ -849,6 +850,7 @@ static void Platform_Battery_getProcData(BatteryInfo* info) {
849850
static void Platform_Battery_getSysData(BatteryInfo* info) {
850851
info->percent = NAN;
851852
info->ac = AC_ERROR;
853+
info->powerCurr = NAN;
852854
info->energyCurr = NAN;
853855
info->energyFull = NAN;
854856

@@ -858,6 +860,9 @@ static void Platform_Battery_getSysData(BatteryInfo* info) {
858860

859861
uint64_t totalFull = 0;
860862
uint64_t totalRemain = 0;
863+
int64_t totalPower = 0;
864+
865+
bool havePower = false;
861866

862867
const struct dirent* dirEntry;
863868
while ((dirEntry = readdir(dir))) {
@@ -910,6 +915,9 @@ static void Platform_Battery_getSysData(BatteryInfo* info) {
910915
uint8_t haveBatteryVoltage = 0; // 0 = no, 1 = min_voltage, 2 = curr_voltage
911916
bool haveBatteryLevel = false;
912917

918+
bool haveBatteryCurrent = false;
919+
bool haveBatteryPower = false;
920+
913921
uint64_t batteryEnergyFull = 0;
914922
uint64_t batteryEnergyCurr = 0;
915923

@@ -919,6 +927,11 @@ static void Platform_Battery_getSysData(BatteryInfo* info) {
919927
uint64_t batteryVoltage = 0;
920928
uint64_t batteryLevel = 0;
921929

930+
int64_t batteryCurrent = 0;
931+
int64_t batteryPower = 0;
932+
933+
bool batteryIsDischarging = false;
934+
922935
const char* line;
923936

924937
char* buf = buffer;
@@ -975,6 +988,18 @@ static void Platform_Battery_getSysData(BatteryInfo* info) {
975988
haveBatteryVoltage = 2;
976989
continue;
977990
}
991+
992+
if (String_eq(field, "CURRENT_NOW")) {
993+
batteryCurrent = val;
994+
haveBatteryCurrent = true;
995+
continue;
996+
}
997+
998+
if (String_eq(field, "POWER_NOW")) {
999+
batteryPower += val;
1000+
haveBatteryPower = true;
1001+
continue;
1002+
}
9781003
}
9791004

9801005
if (haveBatteryLevel) {
@@ -1004,6 +1029,19 @@ static void Platform_Battery_getSysData(BatteryInfo* info) {
10041029
totalFull += batteryEnergyFull;
10051030
totalRemain += batteryEnergyCurr > batteryEnergyFull ? batteryEnergyFull : batteryEnergyCurr;
10061031
}
1032+
1033+
if (!haveBatteryPower && haveBatteryCurrent && haveBatteryVoltage) {
1034+
batteryPower = (batteryCurrent * batteryVoltage) / 1000000;
1035+
haveBatteryPower = true;
1036+
}
1037+
1038+
if (haveBatteryPower) {
1039+
if (batteryIsDischarging)
1040+
batteryPower = -batteryPower;
1041+
1042+
totalPower += batteryPower;
1043+
havePower = true;
1044+
}
10071045
} else if (type == AC) {
10081046
if (info->ac != AC_ERROR)
10091047
goto next;
@@ -1032,6 +1070,10 @@ static void Platform_Battery_getSysData(BatteryInfo* info) {
10321070
info->energyCurr = (double) totalRemain / 1000000.0;
10331071
info->energyFull = (double) totalFull / 1000000.0;
10341072
}
1073+
1074+
if (havePower) {
1075+
info->powerCurr = (double) totalPower / 1000000.0;
1076+
}
10351077
}
10361078

10371079
void Platform_getBattery(BatteryInfo* info) {
@@ -1045,6 +1087,7 @@ void Platform_getBattery(BatteryInfo* info) {
10451087
Platform_Battery_cache = (BatteryInfo) {
10461088
.ac = AC_ERROR,
10471089
.percent = NAN,
1090+
.powerCurr = NAN,
10481091
.energyCurr = NAN,
10491092
.energyFull = NAN,
10501093
};

0 commit comments

Comments
 (0)