Files
linuxSmartie/main.cpp
2025-04-27 10:48:05 +02:00

182 lines
5.4 KiB
C++

#include <sys/statvfs.h>
#include <array>
#include <chrono>
#include <cstdint>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <thread>
#include "include/LCDDisplay.hpp"
#include "include/linux-system-usage.hpp"
#define LCD_PORT "/dev/ttyACM0"
#define LCD_INTERVAL_MS 1000
#define LCD_CONTRAST 225
struct gpuHwmon_t {
std::string fan_speed;
std::string core_clock;
std::string mem_clock;
std::string core_mv;
std::string power_avg;
std::string power_cap;
std::string power_max;
std::string fan_pwm;
std::string edge_temp;
std::string junction_temp;
std::string mem_temp;
};
struct mem_usage_t {
std::string free;
std::string used;
std::string total;
};
std::string pBytes(double i, bool isKbytes = false) {
std::stringstream ss;
std::array suffix = {'K', 'M', 'G', 'T', 'P', 'E', 'Z'};
for (auto &s : suffix) {
if (s == 'K' && isKbytes) continue;
i /= 1024.0;
if (i < 1024) {
ss << std::fixed << std::setprecision(i > 100 ? 1 : 2) << i << s;
return ss.str();
}
}
return "++++";
}
std::string pad(std::string s, uint8_t w, bool ljust = false) {
if (w > s.size()) s.insert(ljust ? s.end() : s.begin(), w - s.size(), ' ');
return s;
}
std::string getAvgs() {
std::stringstream ss;
double avgs[3];
getloadavg(avgs, 3);
ss << std::fixed << std::setprecision(2);
ss << avgs[0] << " " << avgs[1] << " " << avgs[2];
return ss.str();
}
std::array<std::string, 2> getTimeDate() {
std::array months = {"sty", "lut", "mar", "kwi", "maj", "cze", "lip", "sie", "wrz", "paz", "lis", "gru"};
std::array wdays = {"nie", "pon", "wto", "sro", "czw", "pia", "sob"};
auto now = std::time(nullptr);
auto tm = *std::localtime(&now);
std::stringstream time, date;
time << std::setfill('0');
time << std::setw(2) << tm.tm_hour << ":";
time << std::setw(2) << tm.tm_min << ":";
time << std::setw(2) << tm.tm_sec;
date << wdays[tm.tm_wday] << ", " << tm.tm_mday << " " << months[tm.tm_mon];
return {time.str(), date.str()};
}
mem_usage_t getRam() {
mem_usage_t mem;
auto memory_data = get_system_usage_linux::read_memory_data();
mem.free = pBytes(memory_data.available_memory, true);
mem.used = pBytes(memory_data.total_memory - memory_data.available_memory, true);
mem.total = pBytes(memory_data.total_memory, true);
return mem;
}
mem_usage_t getDisk(std::string mount) {
mem_usage_t disk;
struct statvfs diskData;
statvfs(mount.c_str(), &diskData);
disk.free = pBytes(diskData.f_bfree * diskData.f_frsize);
disk.used = pBytes((diskData.f_blocks - diskData.f_bfree) * diskData.f_frsize);
disk.total = pBytes(diskData.f_blocks * diskData.f_frsize);
return disk;
}
std::string readFile(std::string path, uint8_t trim = 0) {
std::string ret;
std::stringstream ss;
std::ifstream fs(path);
if (!fs.good()) {
std::cerr << "Error reading " << path << std::endl;
exit(1);
}
ss << fs.rdbuf();
fs.close();
ret = ss.str();
return ret.substr(0, ret.size() - trim - 1);
}
gpuHwmon_t getGpu(std::string hw) {
gpuHwmon_t gpu;
gpu.fan_speed = readFile(hw + "/fan1_input");
gpu.core_clock = readFile(hw + "/freq1_input", 6);
gpu.mem_clock = readFile(hw + "/freq2_input", 6);
gpu.core_mv = readFile(hw + "/in0_input");
gpu.power_avg = readFile(hw + "/power1_average", 6);
gpu.power_cap = readFile(hw + "/power1_cap", 6);
gpu.power_max = readFile(hw + "/power1_cap_max", 6);
gpu.fan_pwm = readFile(hw + "/pwm1");
gpu.edge_temp = readFile(hw + "/temp1_input", 3);
gpu.junction_temp = readFile(hw + "/temp2_input", 3);
gpu.mem_temp = readFile(hw + "/temp3_input", 3);
return gpu;
}
std::string getCpuTemp() {
return readFile("/sys/devices/pci0000:00/0000:00:18.3/hwmon/hwmon3/temp1_input");
}
void collectAndDraw(LCDDisplay *lcd) {
auto td = getTimeDate();
auto ram = getRam();
auto anime = getDisk("/mnt/anime");
auto home = getDisk("/var/home/drath");
auto gpu = getGpu("/sys/devices/pci0000:00/0000:00:03.1/0000:08:00.0/0000:09:00.0/0000:0a:00.0/hwmon/hwmon2");
std::array<std::string, 4> lines;
lines[0] = td[1] + " " + td[0] + pad(getAvgs(), 20);
lines[1] = pad(ram.used + "/" + ram.total, 13, true) + " ";
lines[1] += pad(gpu.fan_speed + "R", 5) + " ";
lines[1] += pad(gpu.power_avg + "/" + gpu.power_cap + "W", 8) + " ";
lines[1] += pad(gpu.edge_temp + "/" + gpu.junction_temp + "C", 8);
lines[2] = "/home/drath:" + pad(home.free + " free of " + home.total, 28);
lines[3] = "/mnt/anime: " + pad(anime.free + " free of " + anime.total, 28);
lcd->writeLines(lines);
}
int main(int argc, char *argv[]) {
LCDDisplay lcd(LCD_PORT, 0010002);
if (argc > 1 && std::string(argv[1]) == "-d") {
std::cout << "[Chrono] Running in daemon mode, " << LCD_INTERVAL_MS << "ms interval" << std::endl;
lcd.setContrast(LCD_CONTRAST);
lcd.setBacklight(true);
std::chrono::milliseconds interval(LCD_INTERVAL_MS);
auto start = std::chrono::steady_clock::now();
while (true) {
collectAndDraw(&lcd);
std::this_thread::sleep_until(start + interval);
start += interval;
}
} else {
collectAndDraw(&lcd);
}
return 0;
}