mirror of
				https://github.com/rad4day/Waybar.git
				synced 2025-10-31 07:52:42 +01:00 
			
		
		
		
	FreeBSD: Add support to battery
This commit aims to propose a FreeBSD to gain battery support using sysctl on hw.acpi.battery.*
This commit is contained in:
		| @@ -27,7 +27,7 @@ | ||||
| #include "modules/hyprland/language.hpp" | ||||
| #include "modules/hyprland/window.hpp" | ||||
| #endif | ||||
| #if defined(__linux__) && !defined(NO_FILESYSTEM) | ||||
| #if defined(__FreeBSD__) || (defined(__linux__) && !defined(NO_FILESYSTEM)) | ||||
| #include "modules/battery.hpp" | ||||
| #endif | ||||
| #if defined(HAVE_CPU_LINUX) || defined(HAVE_CPU_BSD) | ||||
|   | ||||
| @@ -179,6 +179,11 @@ elif is_dragonfly or is_freebsd or is_netbsd or is_openbsd | ||||
|         'src/modules/memory/bsd.cpp', | ||||
|         'src/modules/memory/common.cpp', | ||||
|     ) | ||||
|     if is_freebsd | ||||
|     src_files += files( | ||||
|         'src/modules/battery.cpp', | ||||
|         ) | ||||
|     endif | ||||
| endif | ||||
|  | ||||
| add_project_arguments('-DHAVE_SWAY', language: 'cpp') | ||||
|   | ||||
| @@ -7,7 +7,7 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { | ||||
|     auto hash_pos = name.find('#'); | ||||
|     auto ref = name.substr(0, hash_pos); | ||||
|     auto id = hash_pos != std::string::npos ? name.substr(hash_pos + 1) : ""; | ||||
| #if defined(__linux__) && !defined(NO_FILESYSTEM) | ||||
| #if defined(__FreeBSD__) || (defined(__linux__) && !defined(NO_FILESYSTEM)) | ||||
|     if (ref == "battery") { | ||||
|       return new waybar::modules::Battery(id, config_[name]); | ||||
|     } | ||||
|   | ||||
| @@ -1,9 +1,16 @@ | ||||
| #include "modules/battery.hpp" | ||||
|  | ||||
| #if defined(__FreeBSD__) | ||||
| // clang-format off | ||||
| #include <sys/types.h> | ||||
| #include <sys/sysctl.h> | ||||
| // clang-format on | ||||
| #endif | ||||
| #include <spdlog/spdlog.h> | ||||
|  | ||||
| #include <iostream> | ||||
| waybar::modules::Battery::Battery(const std::string& id, const Json::Value& config) | ||||
|     : AButton(config, "battery", id, "{capacity}%", 60) { | ||||
| #if defined(__Linux__) | ||||
|   battery_watch_fd_ = inotify_init1(IN_CLOEXEC); | ||||
|   if (battery_watch_fd_ == -1) { | ||||
|     throw std::runtime_error("Unable to listen batteries."); | ||||
| @@ -19,11 +26,12 @@ waybar::modules::Battery::Battery(const std::string& id, const Json::Value& conf | ||||
|   if (global_watch < 0) { | ||||
|     throw std::runtime_error("Could not watch for battery plug/unplug"); | ||||
|   } | ||||
|  | ||||
| #endif | ||||
|   worker(); | ||||
| } | ||||
|  | ||||
| waybar::modules::Battery::~Battery() { | ||||
| #if (__Linux__) | ||||
|   std::lock_guard<std::mutex> guard(battery_list_mutex_); | ||||
|  | ||||
|   if (global_watch >= 0) { | ||||
| @@ -39,9 +47,16 @@ waybar::modules::Battery::~Battery() { | ||||
|     batteries_.erase(it); | ||||
|   } | ||||
|   close(battery_watch_fd_); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void waybar::modules::Battery::worker() { | ||||
| #if defined(__FreeBSD__) | ||||
|   thread_timer_ = [this] { | ||||
|     dp.emit(); | ||||
|     thread_timer_.sleep_for(interval_); | ||||
|   }; | ||||
| #else | ||||
|   thread_timer_ = [this] { | ||||
|     // Make sure we eventually update the list of batteries even if we miss an | ||||
|     // inotify event for some reason | ||||
| @@ -68,9 +83,11 @@ void waybar::modules::Battery::worker() { | ||||
|     refreshBatteries(); | ||||
|     dp.emit(); | ||||
|   }; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void waybar::modules::Battery::refreshBatteries() { | ||||
| #if (__Linux__) | ||||
|   std::lock_guard<std::mutex> guard(battery_list_mutex_); | ||||
|   // Mark existing list of batteries as not necessarily found | ||||
|   std::map<fs::path, bool> check_map; | ||||
| @@ -135,6 +152,7 @@ void waybar::modules::Battery::refreshBatteries() { | ||||
|       batteries_.erase(check.first); | ||||
|     } | ||||
|   } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| // Unknown > Full > Not charging > Discharging > Charging | ||||
| @@ -158,6 +176,49 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g | ||||
|   try { | ||||
|     uint32_t total_power = 0;  // μW | ||||
|     bool total_power_exists = false; | ||||
| #if defined(__FreeBSD__) | ||||
|     int capacity; | ||||
|     size_t size_capacity = sizeof capacity; | ||||
|     if (sysctlbyname("hw.acpi.battery.life", &capacity, &size_capacity, NULL,0) != 0) { | ||||
|       throw std::runtime_error("sysctl hw.acpi.battery.life failed"); | ||||
|     } | ||||
|     int time; | ||||
|     size_t size_time = sizeof time; | ||||
|     if (sysctlbyname("hw.acpi.battery.time", &time, &size_time, NULL,0) != 0) { | ||||
|       throw std::runtime_error("sysctl hw.acpi.battery.time failed"); | ||||
|     } | ||||
|     int rate; | ||||
|     size_t size_rate = sizeof rate; | ||||
|     if (sysctlbyname("hw.acpi.battery.rate", &rate, &size_rate, NULL,0) != 0) { | ||||
|       throw std::runtime_error("sysctl hw.acpi.battery.rate failed"); | ||||
|     } | ||||
|  | ||||
|     auto status = getAdapterStatus(capacity); | ||||
|     // Handle full-at | ||||
|     if (config_["full-at"].isUInt()) { | ||||
|       auto full_at = config_["full-at"].asUInt(); | ||||
|       if (full_at < 100) { | ||||
|         capacity = 100.f * capacity / full_at; | ||||
|       } | ||||
|     } | ||||
|     if (capacity > 100.f) { | ||||
|       // This can happen when the battery is calibrating and goes above 100% | ||||
|       // Handle it gracefully by clamping at 100% | ||||
|       capacity = 100.f; | ||||
|     } | ||||
|     uint8_t cap = round(capacity); | ||||
|     if (cap == 100 && status=="Plugged") { | ||||
|       // If we've reached 100% just mark as full as some batteries can stay | ||||
|       // stuck reporting they're still charging but not yet done | ||||
|       status = "Full"; | ||||
|     } | ||||
|  | ||||
|     //spdlog::info("{} {} {} {}", capacity,time,status,rate); | ||||
|     return {capacity, time, status, rate}; | ||||
|  | ||||
| #else | ||||
|     uint32_t total_power = 0;   // μW | ||||
| >>>>>>> 246e377 (FreeBSD: Add support to battery) | ||||
|     uint32_t total_energy = 0;  // μWh | ||||
|     bool total_energy_exists = false; | ||||
|     uint32_t total_energy_full = 0; | ||||
| @@ -456,6 +517,7 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g | ||||
|     if (cap == 100 && status == "Charging") status = "Full"; | ||||
|  | ||||
|     return {cap, time_remaining, status, total_power / 1e6}; | ||||
| #endif | ||||
|   } catch (const std::exception& e) { | ||||
|     spdlog::error("Battery: {}", e.what()); | ||||
|     return {0, 0, "Unknown", 0}; | ||||
| @@ -463,11 +525,20 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g | ||||
| } | ||||
|  | ||||
| const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) const { | ||||
| #if defined(__Linux__) | ||||
|   if (!adapter_.empty()) { | ||||
|     bool online; | ||||
|     std::string status; | ||||
|     std::ifstream(adapter_ / "online") >> online; | ||||
|     std::getline(std::ifstream(adapter_ / "status"), status); | ||||
| #else | ||||
|     int state; | ||||
|     size_t size_state = sizeof state; | ||||
|     if (sysctlbyname("hw.acpi.battery.state", &state, &size_state, NULL,0) != 0) { | ||||
|       throw std::runtime_error("sysctl hw.acpi.battery.state failed"); | ||||
|     } | ||||
|     bool online = state == 2; | ||||
| #endif | ||||
|     if (capacity == 100) { | ||||
|       return "Full"; | ||||
|     } | ||||
| @@ -475,7 +546,9 @@ const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) c | ||||
|       return "Plugged"; | ||||
|     } | ||||
|     return "Discharging"; | ||||
| #if defined(__Linux__) | ||||
|   } | ||||
| #endif | ||||
|   return "Unknown"; | ||||
| } | ||||
|  | ||||
| @@ -497,10 +570,12 @@ const std::string waybar::modules::Battery::formatTimeRemaining(float hoursRemai | ||||
| } | ||||
|  | ||||
| auto waybar::modules::Battery::update() -> void { | ||||
| #if __Linux__ | ||||
|   if (batteries_.empty()) { | ||||
|     event_box_.hide(); | ||||
|     return; | ||||
|   } | ||||
| #endif | ||||
|   auto [capacity, time_remaining, status, power] = getInfos(); | ||||
|   if (status == "Unknown") { | ||||
|     status = getAdapterStatus(capacity); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Loïc Bartoletti
					Loïc Bartoletti