From c7e2447932738cd635f3b83a7093690ccbb979e1 Mon Sep 17 00:00:00 2001 From: Drath Date: Sun, 28 Dec 2025 19:55:38 +0100 Subject: [PATCH] refactor utils --- include/utils.hpp | 17 +++++++++++++---- main.cpp | 40 ++++++++++++++++++++-------------------- src/cpu.cpp | 22 +++++++++++----------- src/gpu.cpp | 29 ++++++++++++++--------------- src/sys.cpp | 14 +++++++------- src/utils.cpp | 8 ++++++-- 6 files changed, 71 insertions(+), 59 deletions(-) diff --git a/include/utils.hpp b/include/utils.hpp index b533487..5ba6945 100644 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -2,14 +2,18 @@ #define UTILS_HPP #include +#include #include #include -#define FILL_CHAR ' ' +namespace utils { -enum JUST { RIGHT, LEFT }; +const char FILL_CHAR = ' '; -std::string pad(std::string s, uint8_t len, JUST j = JUST::RIGHT); +enum just { right, + left }; + +std::string pad(std::string s, uint8_t len, just j = just::right); std::string center(std::string str, uint8_t len); std::string pBytes(double bytes, bool isKbytes = false); ssize_t readFile(std::string path, char* buffer, size_t maxlen); @@ -22,9 +26,14 @@ inline long long fastReadNum(const std::string& path, char (&buf)[N]) { return std::strtoll(buf, nullptr, 10); } -// pretty prints num with given decs, 0 by default. its basically a macro so we inline it inline std::string pNum(auto num, uint8_t decs = 0) { return std::format("{:.{}f}", num, decs); } +inline bool fileExists(std::string_view path) { + return std::filesystem::exists(path); +} + +} // namespace utils + #endif diff --git a/main.cpp b/main.cpp index 3f1c065..c671691 100644 --- a/main.cpp +++ b/main.cpp @@ -108,7 +108,7 @@ void displayThread(std::stop_token st, Sensors* s) { lcd.setCustomChar(4, {4, 4, 4, 21, 14, 4, 0}); // down arrow // welcome msg - lcd.writeBuf(2, 0, center("Waiting for sensors...", 40)); + lcd.writeBuf(2, 0, utils::center("Waiting for sensors...", 40)); lcd.flushBuf(); lcd.clearBuf(); @@ -121,7 +121,7 @@ void displayThread(std::stop_token st, Sensors* s) { // prepare some tricky sensors std::string gpu_temps = std::to_string(s->gpu.temp_edge); if (s->gpu.temp_hotspot) - gpu_temps = pad(lcd.cc(1) + std::to_string(s->gpu.temp_hotspot - s->gpu.temp_edge) + lcd.cc(0), 4) + " " + pad(gpu_temps + "/" + std::to_string(s->gpu.temp_hotspot), 5); + gpu_temps = utils::pad(lcd.cc(1) + std::to_string(s->gpu.temp_hotspot - s->gpu.temp_edge) + lcd.cc(0), 4) + " " + utils::pad(gpu_temps + "/" + std::to_string(s->gpu.temp_hotspot), 5); uint16_t cpu_fan = 0; for (auto& fan : s->sys.fan_speed) @@ -129,30 +129,30 @@ void displayThread(std::stop_token st, Sensors* s) { cpu_fan /= 2; // write to display buffer - lcd.writeBuf(0, 0, pad(s->td.date, 11, JUST::LEFT) + " " + s->td.time + lcd.bar(7, s->gpu.usage_core / 100.0)); - lcd.writeBuf(0, 26, pNum(s->avg[0], s->avg[0] > 10 ? 1 : 2)); - lcd.writeBuf(0, 31, pNum(s->avg[1], s->avg[1] > 10 ? 1 : 2)); - lcd.writeBuf(0, 36, pNum(s->avg[2], s->avg[2] > 10 ? 1 : 2)); + lcd.writeBuf(0, 0, utils::pad(s->td.date, 11, utils::just::left) + " " + s->td.time + lcd.bar(7, s->gpu.usage_core / 100.0)); + lcd.writeBuf(0, 26, utils::pNum(s->avg[0], s->avg[0] > 10 ? 1 : 2)); + lcd.writeBuf(0, 31, utils::pNum(s->avg[1], s->avg[1] > 10 ? 1 : 2)); + lcd.writeBuf(0, 36, utils::pNum(s->avg[2], s->avg[2] > 10 ? 1 : 2)); - lcd.writeBuf(1, 0, pad(std::to_string(s->cpu.tctl) + "/" + std::to_string(s->cpu.tccd1) + lcd.cc(0), 8, JUST::LEFT)); - lcd.writeBuf(1, 7, pad(pBytes(s->ram.used, true), 6, JUST::LEFT)); - lcd.writeBuf(1, 13, pad(pNum(s->hass_state) + "W", 4)); + lcd.writeBuf(1, 0, utils::pad(std::to_string(s->cpu.tctl) + "/" + std::to_string(s->cpu.tccd1) + lcd.cc(0), 8, utils::just::left)); + lcd.writeBuf(1, 7, utils::pad(utils::pBytes(s->ram.used, true), 6, utils::just::left)); + lcd.writeBuf(1, 13, utils::pad(utils::pNum(s->hass_state) + "W", 4)); lcd.writeBuf(1, 19, std::to_string(s->sys.t_sensor) + lcd.cc(0)); // t_sensor temp - lcd.writeBuf(1, 32 - gpu_temps.size(), pad(pBytes(s->gpu.vram_used), 6)); + lcd.writeBuf(1, 32 - gpu_temps.size(), utils::pad(utils::pBytes(s->gpu.vram_used), 6)); lcd.writeBuf(1, 39 - gpu_temps.size(), gpu_temps + lcd.cc(0)); - lcd.writeBuf(2, 0, pad(std::to_string((int)s->cpu.ptotal) + "W", 8, JUST::LEFT)); + lcd.writeBuf(2, 0, utils::pad(std::to_string((int)s->cpu.ptotal) + "W", 8, utils::just::left)); lcd.writeBuf(2, s->cpu.ptotal < 100 ? 4 : 5, std::to_string(cpu_fan) + "R"); // avg fan speed - lcd.writeBuf(2, 12, lcd.cc(3) + pBytes(s->net.upload)); - lcd.writeBuf(2, 19, lcd.cc(4) + pBytes(s->net.download)); - lcd.writeBuf(2, 26, pad(std::to_string(s->gpu.fan_speed) + "R", 5)); - lcd.writeBuf(2, 31, pad(std::to_string(s->gpu.power_avg) + "/" + std::to_string(s->gpu.power_cap) + "W", 9)); + lcd.writeBuf(2, 12, lcd.cc(3) + utils::pBytes(s->net.upload)); + lcd.writeBuf(2, 19, lcd.cc(4) + utils::pBytes(s->net.download)); + lcd.writeBuf(2, 26, utils::pad(std::to_string(s->gpu.fan_speed) + "R", 5)); + lcd.writeBuf(2, 31, utils::pad(std::to_string(s->gpu.power_avg) + "/" + std::to_string(s->gpu.power_cap) + "W", 9)); - lcd.writeBuf(3, 0, pad(pNum(s->cpu.vcore, 2) + "V", 7, JUST::LEFT)); + lcd.writeBuf(3, 0, utils::pad(utils::pNum(s->cpu.vcore, 2) + "V", 7, utils::just::left)); lcd.writeBuf(3, 6, std::to_string(s->cpu.avg_freq) + "MHz"); - lcd.writeBuf(3, 14, pad(lcd.cc(2) + pBytes(s->home.usage.free), 6)); - lcd.writeBuf(3, 21, pad(std::to_string(s->gpu.clock_core) + "/" + std::to_string(s->gpu.clock_mem) + "MHz ", 13)); - lcd.writeBuf(3, 34, pad(pNum(s->gpu.vcore, 3) + "V", 5)); + lcd.writeBuf(3, 14, utils::pad(lcd.cc(2) + utils::pBytes(s->home.usage.free), 6)); + lcd.writeBuf(3, 21, utils::pad(std::to_string(s->gpu.clock_core) + "/" + std::to_string(s->gpu.clock_mem) + "MHz ", 13)); + lcd.writeBuf(3, 34, utils::pad(utils::pNum(s->gpu.vcore, 3) + "V", 5)); } lcd.flushBuf(); @@ -160,7 +160,7 @@ void displayThread(std::stop_token st, Sensors* s) { } // goodbye msg - lcd.writeBuf(2, 0, center("linuxSmartie closed", 40)); + lcd.writeBuf(2, 0, utils::center("linuxSmartie closed", 40)); lcd.flushBuf(); } diff --git a/src/cpu.cpp b/src/cpu.cpp index 562639b..1f02d59 100644 --- a/src/cpu.cpp +++ b/src/cpu.cpp @@ -11,7 +11,7 @@ void detectHwmon(cpuSensors* target, const std::string& pci) { std::string path = "/sys/bus/pci/devices/" + pci + "/hwmon"; try { - target->hwmon = getFirstDir(path); + target->hwmon = utils::getFirstDir(path); } catch (...) { applog(LOG::ERR, "NO CPU HWMON KERNEL MODULE DETECTED"); return; @@ -34,15 +34,15 @@ void update(cpuSensors* c) { // read power from intel-rapl? works on amd too, btop uses this trick, seems accurate // it tracks with "socket power" in hwinfo on windows, its actually the same thing i had in lcdsmartie curr.ts = std::chrono::steady_clock::now(); - // fastReadNum("/sys/class/powercap/intel-rapl:0/energy_uj", curr.energy); - curr.energy = fastReadNum("/sys/class/powercap/intel-rapl:0/energy_uj", buf); + // utils::fastReadNum("/sys/class/powercap/intel-rapl:0/energy_uj", curr.energy); + curr.energy = utils::fastReadNum("/sys/class/powercap/intel-rapl:0/energy_uj", buf); c->ptotal = (float)(curr.energy - prev.energy) / (float)(std::chrono::duration_cast(curr.ts - prev.ts).count()); prev = curr; // lots of reads but still faster than reading /proc/cpuinfo c->avg_freq = 0; for (uint8_t i = 0; i < N_CPU; i++) { - readFile("/sys/devices/system/cpu/cpu" + std::to_string(i) + "/cpufreq/cpuinfo_avg_freq", buf, sizeof(buf)); + utils::readFile("/sys/devices/system/cpu/cpu" + std::to_string(i) + "/cpufreq/cpuinfo_avg_freq", buf, sizeof(buf)); c->avg_freq += strtol(buf, NULL, 10) / 1000; } c->avg_freq /= N_CPU; @@ -51,14 +51,14 @@ void update(cpuSensors* c) { // commented out unused values so its faster if (c->zenpower) { - c->tdie = fastReadNum(c->hwmon + "/temp1_input", buf) / 1000; - c->tctl = fastReadNum(c->hwmon + "/temp2_input", buf) / 1000; - c->tccd1 = fastReadNum(c->hwmon + "/temp3_input", buf) / 1000; - c->vcore = fastReadNum(c->hwmon + "/in1_input", buf) / 1000.0; - c->vsoc = fastReadNum(c->hwmon + "/in2_input", buf) / 1000.0; + c->tdie = utils::fastReadNum(c->hwmon + "/temp1_input", buf) / 1000; + c->tctl = utils::fastReadNum(c->hwmon + "/temp2_input", buf) / 1000; + c->tccd1 = utils::fastReadNum(c->hwmon + "/temp3_input", buf) / 1000; + c->vcore = utils::fastReadNum(c->hwmon + "/in1_input", buf) / 1000.0; + c->vsoc = utils::fastReadNum(c->hwmon + "/in2_input", buf) / 1000.0; } else { - c->tctl = fastReadNum(c->hwmon + "/temp1_input", buf) / 1000; - c->tccd1 = fastReadNum(c->hwmon + "/temp3_input", buf) / 1000; + c->tctl = utils::fastReadNum(c->hwmon + "/temp1_input", buf) / 1000; + c->tccd1 = utils::fastReadNum(c->hwmon + "/temp3_input", buf) / 1000; } } diff --git a/src/gpu.cpp b/src/gpu.cpp index 8438cb2..8fab334 100644 --- a/src/gpu.cpp +++ b/src/gpu.cpp @@ -11,11 +11,10 @@ namespace gpu { /* takes pointer to a target gpu::sensors struct and updates its hwmon path and detects gpu_metrics */ void detectHwmon(gpuSensors* target, const std::string& pci) { - target->hwmon = getFirstDir("/sys/bus/pci/devices/" + pci + "/hwmon"); + target->hwmon = utils::getFirstDir("/sys/bus/pci/devices/" + pci + "/hwmon"); applog(LOG::INF, "Detected path \"{}\"", target->hwmon); - if (FILE* file = fopen((target->hwmon + REL_METRICS_PATH).c_str(), "r")) { - fclose(file); + if(utils::fileExists(target->hwmon + REL_METRICS_PATH)) { applog(LOG::INF, "found gpu_metrics"); target->hasGpuMetrics = true; } @@ -24,29 +23,29 @@ void detectHwmon(gpuSensors* target, const std::string& pci) { /* some metrics are missing in gpu_metrics, we always fill them from fs, unused metrics are commented out */ void fillMissingMetrics(gpuSensors* g) { static char buf[32]; - g->vcore = fastReadNum(g->hwmon + "/in0_input", buf) / 1000.0; + g->vcore = utils::fastReadNum(g->hwmon + "/in0_input", buf) / 1000.0; // g->fan_pwm = std::stoi(readFile(g->hwmon + "/pwm1", 4)) * 100 / 256; - g->fan_speed = fastReadNum(g->hwmon + "/fan1_input", buf); - g->power_cap = fastReadNum(g->hwmon + "/power1_cap", buf) / 1000000; - // fastReadNum(g->hwmon + "/power1_cap_max", g->power_cap_max) / 1000000; - g->vram_used = fastReadNum(g->hwmon + "/../../mem_info_vram_used", buf); - // fastReadNum(g->hwmon + "/../../mem_info_vram_total", g->vram_total); + g->fan_speed = utils::fastReadNum(g->hwmon + "/fan1_input", buf); + g->power_cap = utils::fastReadNum(g->hwmon + "/power1_cap", buf) / 1000000; + // utils::fastReadNum(g->hwmon + "/power1_cap_max", g->power_cap_max) / 1000000; + g->vram_used = utils::fastReadNum(g->hwmon + "/../../mem_info_vram_used", buf); + // utils::fastReadNum(g->hwmon + "/../../mem_info_vram_total", g->vram_total); } /* get sensors for pre-vega cards (rx480/580) */ void updateFromFs(gpuSensors* g) { static char buf[32]; - g->clock_core = fastReadNum(g->hwmon + "/freq1_input", buf) / 1000000; - g->clock_mem = fastReadNum(g->hwmon + "/freq2_input", buf) / 1000000; - g->power_avg = fastReadNum(g->hwmon + "/power1_input", buf) / 1000000; - g->temp_edge = fastReadNum(g->hwmon + "/temp1_input", buf) / 1000; - g->usage_core = fastReadNum(g->hwmon + "/../../gpu_busy_percent", buf); + g->clock_core = utils::fastReadNum(g->hwmon + "/freq1_input", buf) / 1000000; + g->clock_mem = utils::fastReadNum(g->hwmon + "/freq2_input", buf) / 1000000; + g->power_avg = utils::fastReadNum(g->hwmon + "/power1_input", buf) / 1000000; + g->temp_edge = utils::fastReadNum(g->hwmon + "/temp1_input", buf) / 1000; + g->usage_core = utils::fastReadNum(g->hwmon + "/../../gpu_busy_percent", buf); } /* get sensors for vega and newer (rx5700xt, rx7800xt [*]) */ void updateFromMetrics(gpuSensors* g) { char raw_metrics[MAX_METRICS_LENGTH]; - if (!readFile(g->hwmon + REL_METRICS_PATH, raw_metrics, sizeof(raw_metrics))) return; + if (!utils::readFile(g->hwmon + REL_METRICS_PATH, raw_metrics, sizeof(raw_metrics))) return; auto header = reinterpret_cast(raw_metrics); switch (header->format_revision * 10 + header->content_revision) { diff --git a/src/sys.cpp b/src/sys.cpp index 9a540a2..884b052 100644 --- a/src/sys.cpp +++ b/src/sys.cpp @@ -29,7 +29,7 @@ void sys::getTimeDate(TimeDate* td) { void sys::getRam(Memory* mem) { static char buf[128]; // file is longer but we only need first 128 chars - readFile("/proc/meminfo", buf, sizeof(buf)); + utils::readFile("/proc/meminfo", buf, sizeof(buf)); mem->free = getVal("MemAvailable:", std::string_view(buf)); mem->total = getVal("MemTotal:", std::string_view(buf)); mem->used = mem->total - mem->free; @@ -55,8 +55,8 @@ void sys::getNetwork(Network* net, const std::string& device) { _net current; current.ts = std::chrono::steady_clock::now(); - current.rx = fastReadNum("/sys/class/net/" + device + "/statistics/rx_bytes", buf); - current.tx = fastReadNum("/sys/class/net/" + device + "/statistics/tx_bytes", buf); + current.rx = utils::fastReadNum("/sys/class/net/" + device + "/statistics/rx_bytes", buf); + current.tx = utils::fastReadNum("/sys/class/net/" + device + "/statistics/tx_bytes", buf); float ts_diff = std::chrono::duration_cast(current.ts - prev.ts).count() / 1000000.0f; net->download = (current.rx - prev.rx) / ts_diff; net->upload = (current.tx - prev.tx) / ts_diff; @@ -66,7 +66,7 @@ void sys::getNetwork(Network* net, const std::string& device) { void sys::detectHwmon(sysSensors* s, const std::string& platform) { // we dont really need getFirstDir since its a static folder, but its useful for try/catch try { - s->hwmon = getFirstDir("/sys/devices/platform/" + platform + "/hwmon"); + s->hwmon = utils::getFirstDir("/sys/devices/platform/" + platform + "/hwmon"); } catch (...) { applog(LOG::ERR, "Can't open sys hwmon. Module loaded? Kernel params added?"); return; @@ -77,7 +77,7 @@ void sys::updateSensors(sysSensors* s) { if (s->hwmon.length() < 1) return; static char buf[8]; - s->fan_speed[0] = fastReadNum(s->hwmon + "/fan2_input", buf); - s->fan_speed[1] = fastReadNum(s->hwmon + "/fan7_input", buf); - s->t_sensor = fastReadNum(s->hwmon + "/temp5_input", buf) / 1000; + s->fan_speed[0] = utils::fastReadNum(s->hwmon + "/fan2_input", buf); + s->fan_speed[1] = utils::fastReadNum(s->hwmon + "/fan7_input", buf); + s->t_sensor = utils::fastReadNum(s->hwmon + "/temp5_input", buf) / 1000; } diff --git a/src/utils.cpp b/src/utils.cpp index ae9f004..70de193 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -11,10 +11,12 @@ #include #include +namespace utils { + /* pads given string to length */ -std::string pad(std::string s, uint8_t len, JUST j) { +std::string pad(std::string s, uint8_t len, just j) { if (len > s.size()) - s.insert(j == JUST::LEFT ? s.end() : s.begin(), len - s.size(), FILL_CHAR); + s.insert(j == just::left ? s.end() : s.begin(), len - s.size(), FILL_CHAR); return s; } @@ -65,3 +67,5 @@ std::string getFirstDir(std::string_view path) { return entry.path(); return ""; } + +} \ No newline at end of file