#include #include #include #include #include #include #include #include #include #include #include #include #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 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 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); 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; }