mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-04-10 19:15:13 +00:00
Added a SystemStatus class to poll Bluetooth, Wi-Fi, cellular and battery information from the operating system
This commit is contained in:
parent
b50b4d9d0a
commit
e59f19c2ba
|
@ -123,7 +123,9 @@ if(IOS)
|
|||
elseif(APPLE)
|
||||
include_directories(${COMMON_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
add_executable(ES-DE ${ES_SOURCES} ${ES_HEADERS})
|
||||
target_link_libraries(ES-DE ${COMMON_LIBRARIES} es-core)
|
||||
target_link_libraries(ES-DE ${COMMON_LIBRARIES} "-framework CoreFoundation -framework IOKit"
|
||||
"-framework SystemConfiguration"
|
||||
"-framework IOBluetooth" es-core)
|
||||
set_target_properties(ES-DE PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
if(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 15.0.0)
|
||||
target_link_options(ES-DE PRIVATE LINKER:-no_warn_duplicate_libraries)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "Settings.h"
|
||||
#include "Sound.h"
|
||||
#include "SystemData.h"
|
||||
#include "SystemStatus.h"
|
||||
#include "guis/GuiDetectDevice.h"
|
||||
#include "guis/GuiLaunchScreen.h"
|
||||
#include "utils/FileSystemUtil.h"
|
||||
|
@ -1165,6 +1166,7 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
#endif
|
||||
|
||||
SystemStatus::getInstance();
|
||||
MameNames::getInstance();
|
||||
ThemeData::populateThemes();
|
||||
loadSystemsReturnCode loadSystemsStatus {loadSystemConfigFile()};
|
||||
|
|
|
@ -22,6 +22,7 @@ set(CORE_HEADERS
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/MameNames.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Settings.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Sound.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/SystemStatus.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ThemeData.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Window.h
|
||||
|
||||
|
@ -110,6 +111,7 @@ set(CORE_SOURCES
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/Scripting.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Settings.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Sound.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/SystemStatus.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ThemeData.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Window.cpp
|
||||
|
||||
|
@ -179,6 +181,10 @@ if(ANDROID)
|
|||
set(CORE_SOURCES ${CORE_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/PlatformUtilAndroid.cpp)
|
||||
endif()
|
||||
|
||||
if(APPLE AND NOT IOS)
|
||||
set(CORE_HEADERS ${CORE_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/src/BluetoothStatusApple.m)
|
||||
endif()
|
||||
|
||||
if(IOS)
|
||||
set(CORE_HEADERS ${CORE_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/src/InputOverlay.h)
|
||||
set(CORE_HEADERS ${CORE_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/PlatformUtilIOS.h)
|
||||
|
|
18
es-core/src/BluetoothStatusApple.h
Normal file
18
es-core/src/BluetoothStatusApple.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// ES-DE Frontend
|
||||
// BluetoothStatusApple.h
|
||||
//
|
||||
// Gets the Bluetooth adapter status on macOS.
|
||||
//
|
||||
|
||||
#ifndef ES_CORE_BLUETOOTH_STATUS_APPLE_H
|
||||
#define ES_CORE_BLUETOOTH_STATUS_APPLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
int getBluetoothStatus();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ES_CORE_BLUETOOTH_STATUS_APPLE_H
|
21
es-core/src/BluetoothStatusApple.m
Normal file
21
es-core/src/BluetoothStatusApple.m
Normal file
|
@ -0,0 +1,21 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// ES-DE Frontend
|
||||
// BluetoothStatusApple.m
|
||||
//
|
||||
// Gets the Bluetooth adapter status on macOS.
|
||||
//
|
||||
|
||||
#import "BluetoothStatusApple.h"
|
||||
|
||||
#import <IOBluetooth/IOBluetooth.h>
|
||||
|
||||
int getBluetoothStatus()
|
||||
{
|
||||
IOBluetoothHostController* hciController = [IOBluetoothHostController defaultController];
|
||||
|
||||
if (hciController != NULL && hciController.powerState)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
|
@ -221,6 +221,12 @@ void Settings::setDefaults()
|
|||
#endif
|
||||
mBoolMap["ScreensaverVideoBlur"] = {false, false};
|
||||
|
||||
mBoolMap["SystemStatusDisplayAll"] = {false, false};
|
||||
mBoolMap["SystemStatusBluetooth"] = {true, true};
|
||||
mBoolMap["SystemStatusWifi"] = {true, true};
|
||||
mBoolMap["SystemStatusCellular"] = {true, true};
|
||||
mBoolMap["SystemStatusBattery"] = {true, true};
|
||||
mBoolMap["SystemStatusBatteryPercentage"] = {true, true};
|
||||
mBoolMap["ThemeVariantTriggers"] = {true, true};
|
||||
mBoolMap["DisplayClock"] = {false, false};
|
||||
mBoolMap["MenuBlurBackground"] = {true, true};
|
||||
|
|
444
es-core/src/SystemStatus.cpp
Normal file
444
es-core/src/SystemStatus.cpp
Normal file
|
@ -0,0 +1,444 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// ES-DE Frontend
|
||||
// SystemStatus.cpp
|
||||
//
|
||||
// Queries system status information from the operating system.
|
||||
// This includes Bluetooth, Wi-Fi, cellular and battery.
|
||||
//
|
||||
|
||||
#include "SystemStatus.h"
|
||||
|
||||
#include "Log.h"
|
||||
#include "Settings.h"
|
||||
#include "utils/FileSystemUtil.h"
|
||||
#include "utils/StringUtil.h"
|
||||
|
||||
#include <SDL2/SDL_timer.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#if defined(__APPLE__) && !defined(__IOS__)
|
||||
#include "BluetoothStatusApple.h"
|
||||
#include <IOKit/ps/IOPSKeys.h>
|
||||
#include <IOKit/ps/IOPowerSources.h>
|
||||
#include <SystemConfiguration/SCNetworkConfiguration.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN64)
|
||||
// clang-format off
|
||||
// Because of course building fails if the files are included in the "wrong" order.
|
||||
#include <windows.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <bluetoothapis.h>
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include "utils/PlatformUtilAndroid.h"
|
||||
#endif
|
||||
|
||||
#define DEBUG_SYSTEM_STATUS false
|
||||
|
||||
SystemStatus::SystemStatus() noexcept
|
||||
: mExitPolling {false}
|
||||
, mPollImmediately {false}
|
||||
, mHasBluetooth {false}
|
||||
, mHasWifi {false}
|
||||
, mHasCellular {false}
|
||||
, mHasBattery {false}
|
||||
, mBatteryCharging {false}
|
||||
, mBatteryCapacity {0}
|
||||
|
||||
{
|
||||
setCheckFlags();
|
||||
mPollThread = std::make_unique<std::thread>(&SystemStatus::pollStatus, this);
|
||||
}
|
||||
|
||||
SystemStatus::~SystemStatus()
|
||||
{
|
||||
mExitPolling = true;
|
||||
|
||||
if (mPollThread != nullptr && mPollThread->joinable()) {
|
||||
mPollThread->join();
|
||||
mPollThread.reset();
|
||||
}
|
||||
}
|
||||
|
||||
SystemStatus& SystemStatus::getInstance()
|
||||
{
|
||||
static SystemStatus instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void SystemStatus::setCheckFlags()
|
||||
{
|
||||
std::unique_lock<std::mutex> statusLock {mStatusMutex};
|
||||
mCheckBluetooth = Settings::getInstance()->getBool("SystemStatusBluetooth");
|
||||
mCheckWifi = Settings::getInstance()->getBool("SystemStatusWifi");
|
||||
mCheckCellular = Settings::getInstance()->getBool("SystemStatusCellular");
|
||||
mCheckBattery = Settings::getInstance()->getBool("SystemStatusBattery");
|
||||
}
|
||||
|
||||
void SystemStatus::setPolling(const bool state)
|
||||
{
|
||||
if (state == false) {
|
||||
mExitPolling = true;
|
||||
if (mPollThread != nullptr && mPollThread->joinable()) {
|
||||
mPollThread->join();
|
||||
mPollThread.reset();
|
||||
}
|
||||
}
|
||||
else if (mPollThread == nullptr) {
|
||||
mExitPolling = false;
|
||||
mPollThread = std::make_unique<std::thread>(&SystemStatus::pollStatus, this);
|
||||
}
|
||||
}
|
||||
|
||||
SystemStatus::Status SystemStatus::getStatus()
|
||||
{
|
||||
mStatus.hasBluetooth = mHasBluetooth;
|
||||
mStatus.hasWifi = mHasWifi;
|
||||
mStatus.hasCellular = mHasCellular;
|
||||
mStatus.hasBattery = mHasBattery;
|
||||
mStatus.batteryCharging = mBatteryCharging;
|
||||
mStatus.batteryCapacity = mBatteryCapacity;
|
||||
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
void SystemStatus::pollStatus()
|
||||
{
|
||||
while (!mExitPolling) {
|
||||
std::unique_lock<std::mutex> statusLock {mStatusMutex};
|
||||
|
||||
getStatusBluetooth();
|
||||
getStatusWifi();
|
||||
getStatusCellular();
|
||||
getStatusBattery();
|
||||
statusLock.unlock();
|
||||
|
||||
#if (DEBUG_SYSTEM_STATUS)
|
||||
std::string status {"Bluetooth "};
|
||||
status.append(mHasBluetooth ? "enabled" : "disabled")
|
||||
.append(", Wi-Fi ")
|
||||
.append(mHasBluetooth ? "enabled" : "disabled")
|
||||
.append(", cellular ")
|
||||
.append(mHasCellular ? "enabled" : "disabled")
|
||||
.append(", battery ")
|
||||
.append(mHasBattery ? "enabled" : "disabled");
|
||||
if (mHasBattery) {
|
||||
status.append(" (")
|
||||
.append(mBatteryCharging ? "charging" : "not charging")
|
||||
.append(" and at ")
|
||||
.append(std::to_string(mBatteryCapacity))
|
||||
.append("% capacity)");
|
||||
}
|
||||
LOG(LogDebug) << "SystemStatus::pollStatus(): " << status;
|
||||
#endif
|
||||
|
||||
int delayValue {0};
|
||||
while (!mPollImmediately && !mExitPolling && delayValue < 3000) {
|
||||
delayValue += 100;
|
||||
SDL_Delay(100);
|
||||
}
|
||||
|
||||
mPollImmediately = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SystemStatus::getStatusBluetooth()
|
||||
{
|
||||
if (!mCheckBluetooth)
|
||||
return;
|
||||
|
||||
bool hasBluetooth {false};
|
||||
|
||||
#if defined(__APPLE__) && !defined(__IOS__)
|
||||
if (getBluetoothStatus() == 1)
|
||||
hasBluetooth = true;
|
||||
|
||||
#elif defined(_WIN64)
|
||||
BLUETOOTH_FIND_RADIO_PARAMS btFindRadio {sizeof(BLUETOOTH_FIND_RADIO_PARAMS)};
|
||||
HANDLE btRadio {nullptr};
|
||||
BLUETOOTH_RADIO_INFO btInfo {sizeof(BLUETOOTH_RADIO_INFO), 0};
|
||||
|
||||
if (BluetoothFindFirstRadio(&btFindRadio, &btRadio) != nullptr) {
|
||||
if (BluetoothGetRadioInfo(btRadio, &btInfo) == ERROR_SUCCESS)
|
||||
hasBluetooth = true;
|
||||
}
|
||||
|
||||
#elif defined(__ANDROID__)
|
||||
if (Utils::Platform::Android::getBluetoothStatus())
|
||||
hasBluetooth = true;
|
||||
|
||||
#elif defined(__linux__)
|
||||
const std::string sysEntry {"/sys/class/rfkill"};
|
||||
auto entries {Utils::FileSystem::getDirContent(sysEntry, false)};
|
||||
for (auto& entry : entries) {
|
||||
if (Utils::FileSystem::exists(entry + "/type")) {
|
||||
std::string type;
|
||||
std::ifstream fileStream;
|
||||
fileStream.open(entry + "/type");
|
||||
getline(fileStream, type);
|
||||
fileStream.close();
|
||||
if (Utils::String::toLower(type) == "bluetooth") {
|
||||
std::string state;
|
||||
fileStream.open(entry + "/state");
|
||||
getline(fileStream, state);
|
||||
fileStream.close();
|
||||
if (std::stoi(state) == 1)
|
||||
hasBluetooth = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
mHasBluetooth = hasBluetooth;
|
||||
}
|
||||
|
||||
void SystemStatus::getStatusWifi()
|
||||
{
|
||||
if (!mCheckWifi)
|
||||
return;
|
||||
|
||||
bool hasWifi {false};
|
||||
|
||||
#if defined(__APPLE__) && !defined(__IOS__)
|
||||
const CFArrayRef interfaces {SCNetworkInterfaceCopyAll()};
|
||||
|
||||
if (interfaces != nullptr) {
|
||||
for (CFIndex i {0}; i < CFArrayGetCount(interfaces); ++i) {
|
||||
SCNetworkInterfaceRef interface {
|
||||
static_cast<SCNetworkInterfaceRef>(CFArrayGetValueAtIndex(interfaces, i))};
|
||||
|
||||
if (SCNetworkInterfaceGetInterfaceType(interface) == kSCNetworkInterfaceTypeIEEE80211) {
|
||||
const CFStringRef bsdName {SCNetworkInterfaceGetBSDName(interface)};
|
||||
|
||||
const SCDynamicStoreRef session {
|
||||
SCDynamicStoreCreate(nullptr, CFSTR("Custom"), nullptr, nullptr)};
|
||||
|
||||
const CFStringRef resolvedQuery {CFStringCreateWithFormat(
|
||||
nullptr, nullptr, CFSTR("State:/Network/Interface/%@/IPv4"), bsdName)};
|
||||
|
||||
const CFDictionaryRef dict {
|
||||
static_cast<CFDictionaryRef>(SCDynamicStoreCopyValue(session, resolvedQuery))};
|
||||
|
||||
if (dict != nullptr) {
|
||||
hasWifi = true;
|
||||
CFRelease(dict);
|
||||
CFRelease(resolvedQuery);
|
||||
CFRelease(session);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
CFRelease(resolvedQuery);
|
||||
CFRelease(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
CFRelease(interfaces);
|
||||
}
|
||||
|
||||
#elif defined(_WIN64)
|
||||
PIP_ADAPTER_INFO pAdapterInfo {nullptr};
|
||||
PIP_ADAPTER_INFO pAdapter {nullptr};
|
||||
ULONG ulOutBufLen {sizeof(IP_ADAPTER_INFO)};
|
||||
pAdapterInfo = reinterpret_cast<IP_ADAPTER_INFO*>(malloc(sizeof(IP_ADAPTER_INFO)));
|
||||
|
||||
if (pAdapterInfo != nullptr) {
|
||||
// Make an initial call to GetAdaptersInfo to get the necessary size into the
|
||||
// ulOutBufLen variable, which may or may not be big enough.
|
||||
if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
|
||||
free(pAdapterInfo);
|
||||
pAdapterInfo = reinterpret_cast<IP_ADAPTER_INFO*>(malloc(ulOutBufLen));
|
||||
}
|
||||
if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == NO_ERROR) {
|
||||
pAdapter = pAdapterInfo;
|
||||
while (pAdapter) {
|
||||
if (pAdapter->Type == IF_TYPE_IEEE80211) {
|
||||
// Checking whether the interface has an IP address is crude but
|
||||
// it seems to get the job done. And there is no other obvious
|
||||
// way to query the interface status without using additional
|
||||
// convoluted API calls.
|
||||
if (const std::string {pAdapter->IpAddressList.IpAddress.String} != "0.0.0.0") {
|
||||
hasWifi = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pAdapter = pAdapter->Next;
|
||||
}
|
||||
}
|
||||
|
||||
if (pAdapterInfo)
|
||||
free(pAdapterInfo);
|
||||
}
|
||||
|
||||
#elif defined(__ANDROID__)
|
||||
if (Utils::Platform::Android::getWifiStatus() == 1)
|
||||
hasWifi = true;
|
||||
|
||||
#elif defined(__linux__)
|
||||
const std::string sysEntry {"/sys/class/net"};
|
||||
auto entries {Utils::FileSystem::getDirContent(sysEntry, false)};
|
||||
for (auto& entry : entries) {
|
||||
if (Utils::FileSystem::exists(entry + "/wireless") &&
|
||||
Utils::FileSystem::exists(entry + "/operstate")) {
|
||||
std::string wifiState;
|
||||
std::ifstream fileStream;
|
||||
fileStream.open(entry + "/operstate");
|
||||
getline(fileStream, wifiState);
|
||||
fileStream.close();
|
||||
if (Utils::String::toLower(wifiState) == "up")
|
||||
hasWifi = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
mHasWifi = hasWifi;
|
||||
}
|
||||
|
||||
void SystemStatus::getStatusCellular()
|
||||
{
|
||||
if (!mCheckCellular)
|
||||
return;
|
||||
|
||||
bool hasCellular {false};
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
if (Utils::Platform::Android::getCellularStatus() >= 1)
|
||||
hasCellular = true;
|
||||
#endif
|
||||
|
||||
mHasCellular = hasCellular;
|
||||
}
|
||||
|
||||
void SystemStatus::getStatusBattery()
|
||||
{
|
||||
if (!mCheckBattery)
|
||||
return;
|
||||
|
||||
bool hasBattery {false};
|
||||
bool batteryCharging {false};
|
||||
int batteryCapacity {0};
|
||||
|
||||
#if defined(__APPLE__) && !defined(__IOS__)
|
||||
CFTypeRef sourceInfo {IOPSCopyPowerSourcesInfo()};
|
||||
CFArrayRef sourceList {IOPSCopyPowerSourcesList(sourceInfo)};
|
||||
|
||||
if (sourceList != nullptr && CFArrayGetCount(sourceList) > 0) {
|
||||
CFDictionaryRef source {nullptr};
|
||||
|
||||
for (CFIndex i {0}; i < CFArrayGetCount(sourceList); ++i) {
|
||||
source =
|
||||
IOPSGetPowerSourceDescription(sourceInfo, CFArrayGetValueAtIndex(sourceList, i));
|
||||
// Check if this is a battery.
|
||||
const CFStringRef type {static_cast<CFStringRef>(
|
||||
CFDictionaryGetValue(source, CFSTR(kIOPSTransportTypeKey)))};
|
||||
if (kCFCompareEqualTo == CFStringCompare(type, CFSTR(kIOPSInternalType), 0))
|
||||
break;
|
||||
else
|
||||
source = nullptr;
|
||||
}
|
||||
|
||||
if (source != nullptr) {
|
||||
hasBattery = true;
|
||||
|
||||
if (CFDictionaryGetValue(source, CFSTR(kIOPSIsChargingKey)) != nullptr) {
|
||||
batteryCharging = CFBooleanGetValue(static_cast<CFBooleanRef>(
|
||||
CFDictionaryGetValue(source, CFSTR(kIOPSIsChargingKey))));
|
||||
}
|
||||
|
||||
int curCapacity {0};
|
||||
const CFNumberRef curCapacityNum {static_cast<CFNumberRef>(
|
||||
CFDictionaryGetValue(source, CFSTR(kIOPSCurrentCapacityKey)))};
|
||||
CFNumberGetValue(curCapacityNum, kCFNumberIntType, &curCapacity);
|
||||
|
||||
int maxCapacity {0};
|
||||
const CFNumberRef maxCapacityNum {
|
||||
static_cast<CFNumberRef>(CFDictionaryGetValue(source, CFSTR(kIOPSMaxCapacityKey)))};
|
||||
CFNumberGetValue(maxCapacityNum, kCFNumberIntType, &maxCapacity);
|
||||
|
||||
if (maxCapacity > 0)
|
||||
batteryCapacity = curCapacity / maxCapacity * 100;
|
||||
}
|
||||
}
|
||||
|
||||
if (sourceInfo != nullptr)
|
||||
CFRelease(sourceInfo);
|
||||
if (sourceList != nullptr)
|
||||
CFRelease(sourceList);
|
||||
|
||||
#elif defined(_WIN64)
|
||||
SYSTEM_POWER_STATUS powerStatus;
|
||||
|
||||
if (GetSystemPowerStatus(&powerStatus)) {
|
||||
if (powerStatus.BatteryFlag != 128 && powerStatus.BatteryFlag != 255) {
|
||||
hasBattery = true;
|
||||
|
||||
if (powerStatus.ACLineStatus == 1)
|
||||
atteryCharging = true;
|
||||
|
||||
batteryCapacity = powerStatus.BatteryLifePercent;
|
||||
}
|
||||
else {
|
||||
hasBattery = false;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__ANDROID__)
|
||||
std::pair<int, int> batteryStatus {Utils::Platform::Android::getBatteryStatus()};
|
||||
hasBattery = static_cast<bool>(batteryStatus.first);
|
||||
|
||||
if (batteryStatus.first == -1 && batteryStatus.second == -1) {
|
||||
hasBattery = false;
|
||||
}
|
||||
else {
|
||||
hasBattery = true;
|
||||
if (batteryStatus.first == 1)
|
||||
batteryCharging = true;
|
||||
}
|
||||
|
||||
batteryCapacity = batteryStatus.second;
|
||||
|
||||
#elif defined(__linux__)
|
||||
const std::string sysEntry {"/sys/class/power_supply"};
|
||||
std::string batteryDir;
|
||||
auto entries {Utils::FileSystem::getDirContent(sysEntry, false)};
|
||||
if (std::find(entries.cbegin(), entries.cend(), sysEntry + "/BAT0") != entries.cend())
|
||||
batteryDir = sysEntry + "/BAT0";
|
||||
else if (std::find(entries.cbegin(), entries.cend(), sysEntry + "/BAT1") != entries.cend())
|
||||
batteryDir = sysEntry + "/BAT1";
|
||||
else if (std::find(entries.cbegin(), entries.cend(), sysEntry + "/battery") != entries.cend())
|
||||
batteryDir = sysEntry + "/battery";
|
||||
|
||||
if (!Utils::FileSystem::exists(batteryDir + "/status"))
|
||||
hasBattery = false;
|
||||
if (!Utils::FileSystem::exists(batteryDir + "/capacity"))
|
||||
hasBattery = false;
|
||||
|
||||
if (hasBattery) {
|
||||
std::string batteryStatusValue;
|
||||
std::string batteryCapacityValue;
|
||||
std::ifstream fileStream;
|
||||
fileStream.open(batteryDir + "/status");
|
||||
getline(fileStream, batteryStatusValue);
|
||||
batteryStatusValue = Utils::String::toLower(batteryStatusValue);
|
||||
fileStream.close();
|
||||
|
||||
if (batteryStatusValue != "discharging")
|
||||
batteryCharging = true;
|
||||
|
||||
fileStream.open(batteryDir + "/capacity");
|
||||
getline(fileStream, batteryCapacityValue);
|
||||
fileStream.close();
|
||||
|
||||
batteryCapacity = std::stoi(batteryCapacityValue);
|
||||
}
|
||||
#endif
|
||||
|
||||
mHasBattery = hasBattery;
|
||||
mBatteryCharging = batteryCharging;
|
||||
mBatteryCapacity = batteryCapacity;
|
||||
}
|
77
es-core/src/SystemStatus.h
Normal file
77
es-core/src/SystemStatus.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// ES-DE Frontend
|
||||
// SystemStatus.h
|
||||
//
|
||||
// Queries system status information from the operating system.
|
||||
// This includes Bluetooth, Wi-Fi, cellular and battery.
|
||||
//
|
||||
|
||||
#ifndef ES_CORE_SYSTEM_STATUS_H
|
||||
#define ES_CORE_SYSTEM_STATUS_H
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
class SystemStatus
|
||||
{
|
||||
public:
|
||||
~SystemStatus();
|
||||
static SystemStatus& getInstance();
|
||||
|
||||
void setCheckFlags();
|
||||
void setPolling(const bool state);
|
||||
void pollImmediately() { mPollImmediately = true; }
|
||||
|
||||
struct Status {
|
||||
bool hasBluetooth;
|
||||
bool hasWifi;
|
||||
bool hasCellular;
|
||||
bool hasBattery;
|
||||
bool batteryCharging;
|
||||
int batteryCapacity;
|
||||
Status()
|
||||
: hasBluetooth {false}
|
||||
, hasWifi {false}
|
||||
, hasCellular {false}
|
||||
, hasBattery {false}
|
||||
, batteryCharging {false}
|
||||
, batteryCapacity {0}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
Status getStatus();
|
||||
|
||||
private:
|
||||
SystemStatus() noexcept;
|
||||
|
||||
void pollStatus();
|
||||
|
||||
void getStatusBluetooth();
|
||||
void getStatusWifi();
|
||||
void getStatusCellular();
|
||||
void getStatusBattery();
|
||||
|
||||
bool mCheckBluetooth;
|
||||
bool mCheckWifi;
|
||||
bool mCheckCellular;
|
||||
bool mCheckBattery;
|
||||
|
||||
std::unique_ptr<std::thread> mPollThread;
|
||||
Status mStatus;
|
||||
std::mutex mStatusMutex;
|
||||
|
||||
std::atomic<bool> mExitPolling;
|
||||
std::atomic<bool> mPollImmediately;
|
||||
|
||||
std::atomic<bool> mHasBluetooth;
|
||||
std::atomic<bool> mHasWifi;
|
||||
std::atomic<bool> mHasCellular;
|
||||
std::atomic<bool> mHasBattery;
|
||||
std::atomic<bool> mBatteryCharging;
|
||||
std::atomic<int> mBatteryCapacity;
|
||||
};
|
||||
|
||||
#endif // ES_CORE_SYSTEM_STATUS_H
|
Loading…
Reference in a new issue