Go to the documentation of this file.00001
00010 #include "BatteryState.h"
00011 #include "DetectOS.h"
00012 #if defined(WINDOWS_OS)
00013 #include <windows.h>
00014 #else
00015 #include "split.h"
00016 #include <algorithm>
00017 #include <string>
00018 #include <fstream>
00019 #include <cstdlib>
00020 #endif
00021
00022 using namespace qrk;
00023 using namespace std;
00024
00025
00026 #if defined(WINDOWS_OS)
00027 struct BatteryState::pImpl
00028 {
00029 bool isAvailable(void)
00030 {
00031 SYSTEM_POWER_STATUS status;
00032 if (! GetSystemPowerStatus(&status)) {
00033 return false;
00034 }
00035 return (status.BatteryLifePercent == 255) ? false : true;
00036 }
00037
00038
00039 bool isCharging(void)
00040 {
00041 SYSTEM_POWER_STATUS status;
00042 if (! GetSystemPowerStatus(&status)) {
00043 return false;
00044 }
00045 return (static_cast<int>(status.ACLineStatus) == 1) ? true : false;
00046 }
00047
00048
00049 size_t remainingPercent(void)
00050 {
00051 SYSTEM_POWER_STATUS status;
00052 if (! GetSystemPowerStatus(&status)) {
00053 return 0;
00054 }
00055 return status.BatteryLifePercent;
00056 }
00057
00058
00059 size_t remainingSecond(void)
00060 {
00061 SYSTEM_POWER_STATUS status;
00062 if (! GetSystemPowerStatus(&status)) {
00063 return 0;
00064 }
00065 return max(0, static_cast<int>(status.BatteryLifeTime));
00066 }
00067 };
00068 #else
00069
00070 struct BatteryState::pImpl
00071 {
00072 bool is_available_;
00073 size_t full_capacity_;
00074 string state_file_;
00075 string info_file_;
00076
00077
00078 pImpl(void) : is_available_(false), full_capacity_(1)
00079 {
00080
00081 for (size_t id = 0; id < 2; ++id) {
00082 char buffer[] = "BAT0";
00083 snprintf(buffer, sizeof(buffer), "BAT%d", id);
00084
00085 state_file_ = "/proc/acpi/battery/" + string(buffer) + "/state";
00086 info_file_ = "/proc/acpi/battery/" + string(buffer) + "/info";
00087
00088 if (loadFullCapacity()) {
00089 break;
00090 }
00091 }
00092 }
00093
00094
00095 bool matchData(string& value, const char* file, const char* pattern) const
00096 {
00097 ifstream fin(file);
00098 if (! fin.is_open()) {
00099 return false;
00100 }
00101
00102
00103 string line;
00104 while (getline(fin, line)) {
00105 vector<string> tokens;
00106 if (split(tokens, line, ":") >= 2) {
00107 if (! tokens[0].compare(pattern)) {
00108 string& token = tokens[1];
00109 size_t first_index = 0;
00110 while (token[first_index] == ' ') {
00111 ++first_index;
00112 }
00113 value = &token[first_index];
00114 return true;
00115 }
00116 }
00117 }
00118 return false;
00119 }
00120
00121
00122 bool matchData(size_t& value, const char* file, const char* pattern) const
00123 {
00124 string string_value;
00125 if (! matchData(string_value, file, pattern)) {
00126 return false;
00127 }
00128
00129 value = atoi(string_value.c_str());
00130 return true;
00131 }
00132
00133
00134 bool loadFullCapacity(void)
00135 {
00136
00137
00138 if ((matchData(full_capacity_,
00139 info_file_.c_str(), "last full capacity")) &&
00140 (full_capacity_ > 0)) {
00141 is_available_ = true;
00142 return true;
00143 }
00144
00145 return false;
00146 }
00147
00148
00149 bool isAvailable(void) const
00150 {
00151 return is_available_;
00152 }
00153
00154
00155 bool isCharging(void) const
00156 {
00157 if (! is_available_) {
00158 return false;
00159 }
00160
00161
00162
00163 string state;
00164 if (matchData(state, state_file_.c_str(), "charging state") &&
00165 ((! state.compare("charged")) || (! state.compare("charging")))) {
00166 return true;
00167 }
00168
00169 return false;
00170 }
00171
00172
00173 size_t remainingPercent(void) const
00174 {
00175 if (! is_available_) {
00176 return 0;
00177 }
00178
00179
00180
00181 size_t remaining_capacity = 0;
00182 if (! matchData(remaining_capacity,
00183 state_file_.c_str(), "remaining capacity")) {
00184 return 0;
00185 }
00186
00187 size_t percent = min(static_cast<size_t>(100),
00188 100 * remaining_capacity / full_capacity_);
00189
00190 return percent;
00191 }
00192
00193
00194 size_t remainingSecond(void) const
00195 {
00196 if (! is_available_) {
00197 return 0;
00198 }
00199
00200 if (isCharging()) {
00201 return 0;
00202 }
00203
00204
00205
00206
00207 size_t present_rate = 0;
00208 if (! matchData(present_rate, state_file_.c_str(), "present rate")) {
00209 return 0;
00210 }
00211
00212 size_t remaining_capacity = 0;
00213 if (! matchData(remaining_capacity,
00214 state_file_.c_str(), "remaining capacity")) {
00215 return 0;
00216 }
00217
00218 size_t second =
00219 60 * 60 * remaining_capacity / max(present_rate,
00220 static_cast<size_t>(1));
00221 return second;
00222 }
00223 };
00224 #endif
00225
00226
00227 BatteryState::BatteryState(void) : pimpl(new pImpl)
00228 {
00229 }
00230
00231
00232 BatteryState::~BatteryState(void)
00233 {
00234 }
00235
00236
00237 bool BatteryState::isAvailable(void) const
00238 {
00239 return pimpl->isAvailable();
00240 }
00241
00242
00243 bool BatteryState::isCharging(void) const
00244 {
00245 return pimpl->isCharging();
00246 }
00247
00248
00249 size_t BatteryState::remainingPercent(void) const
00250 {
00251 return pimpl->remainingPercent();
00252 }
00253
00254
00255 size_t BatteryState::remainingSecond(void) const
00256 {
00257 return pimpl->remainingSecond();
00258 }