Files
linuxSmartie/main.cpp

190 lines
5.5 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/gpu.hpp"
#include "include/utils.hpp"
#define LCD_PORT "/dev/ttyACM0"
#define LCD_INTERVAL_MS 1000
#define LCD_CONTRAST 215
#define FILL_CHAR ' '
struct mem_usage_t {
uint64_t free;
uint64_t used;
uint64_t total;
};
/* DISPLAY FUNCS */
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) {
uint8_t p = 2;
if (i > 10) p = 1;
if (i > 100) p = 0;
ss << std::fixed << std::setprecision(p) << i << s;
return ss.str();
}
}
return "++++";
}
// converts number to string with given decimal places
std::string pNum(auto num, uint8_t decs = 0) {
std::stringstream ss;
ss << std::fixed << std::setprecision(decs) << num;
return ss.str();
}
// pads given string to size
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(), FILL_CHAR);
return s;
}
// fills n spaces
std::string fill(uint8_t n) {
return std::string(n, FILL_CHAR);
}
/* getters */
std::string getAvgs() {
std::stringstream ss;
double avgs[3];
getloadavg(avgs, 3);
for (uint8_t i = 0; i < 3; i++) {
ss << std::fixed << std::setprecision(avgs[i] > 10 ? 1 : 2);
ss << " " << avgs[i];
}
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;
std::ifstream proc_meminfo("/proc/meminfo");
if (proc_meminfo.good()) {
std::string content((std::istreambuf_iterator<char>(proc_meminfo)), std::istreambuf_iterator<char>());
mem.free = get_val("MemAvailable:", content);
mem.total = get_val("MemTotal:", content);
mem.used = mem.total - mem.free;
}
proc_meminfo.close();
return mem;
}
mem_usage_t getDisk(std::string mount) {
mem_usage_t disk;
struct statvfs diskData;
statvfs(mount.c_str(), &diskData);
disk.free = diskData.f_bfree * diskData.f_frsize;
disk.used = (diskData.f_blocks - diskData.f_bfree) * diskData.f_frsize;
disk.total = diskData.f_blocks * diskData.f_frsize;
return disk;
}
auto getCpuTemp(std::string hw) {
struct {
double tctl;
double tccd1;
} cpu;
cpu.tctl = (double)(std::stoul(readFile(hw + "/temp1_input")) / 1000.0);
cpu.tccd1 = (double)(std::stoul(readFile(hw + "/temp3_input")) / 1000.0);
return cpu;
}
void collectAndDraw(LCDDisplay *lcd) {
}
int main(int argc, char *argv[]) {
bool daemon_mode = (argc > 1 && std::string(argv[1]) == "-d");
/* init lcd, set contrast and backlight */
LCDDisplay lcd(LCD_PORT, 0010002);
if (daemon_mode) {
lcd.setContrast(LCD_CONTRAST);
lcd.setBacklight(true);
}
/* initial vars */
std::array<std::string, 4> lines;
auto cpu_hwmon = findHwmonPath("k10temp");
auto gpu_hwmon = "/sys/class/drm/card1/device";
/* loop setup */
std::cout << "[Chrono] Running in daemon mode, " << LCD_INTERVAL_MS << "ms interval" << std::endl;
std::chrono::milliseconds interval(LCD_INTERVAL_MS);
auto start = std::chrono::steady_clock::now();
/* main loop */
while (true) {
auto td = getTimeDate();
auto ram = getRam();
auto anime = getDisk("/mnt/anime");
auto home = getDisk("/var/home/drath");
auto gpu = getGpu(gpu_hwmon);
auto cpu = getCpuTemp(cpu_hwmon);
lines[0] = td[1] + " " + td[0] + pad(getAvgs(), 20);
lines[1] = pad(pNum(cpu.tctl) + "/" + pNum(cpu.tccd1) + "C", 8, true);
lines[1] += pad(pBytes(ram.used, true) + "B", 7, true);
lines[1] += fill(7);
lines[1] += pad(pBytes(gpu.vram_used) + "B", 7);
lines[1] += pad(std::to_string(gpu.edge_temp) + "/" + std::to_string(gpu.hotspot_temp) + "/" + std::to_string(gpu.mem_temp) + "C", 11);
lines[2] = pad("home: " + pBytes(home.free), 11, true);
lines[2] += fill(15);
lines[2] += pad(pNum(gpu.fan_speed) + "R", 5);
lines[2] += pad(std::to_string(gpu.power_avg) + "/" + std::to_string(gpu.power_cap) + "W", 9);
lines[3] = pad("anime: " + pBytes(anime.free), 13, true);
lines[3] += fill(8);
lines[3] += pad(pNum(gpu.core_clock) + "/" + pNum(gpu.mem_clock) + "MHz ", 13);
lines[3] += pad(pNum(gpu.vcore, 3) + "V", 5);
lcd.writeLines(lines);
if (daemon_mode) {
std::this_thread::sleep_until(start + interval);
start += interval;
} else {
break;
}
}
return 0;
}