lotsa changes again

This commit is contained in:
Drath
2025-09-13 18:00:56 +02:00
parent b1ce4a1904
commit e8dc798e26

138
main.cpp
View File

@@ -4,9 +4,10 @@
#include <csignal> #include <csignal>
#include <cstdint> #include <cstdint>
#include <cstdlib> #include <cstdlib>
#include <iostream> #include <memory>
#include <mutex>
#include <print> #include <print>
#include <sstream> #include <semaphore>
#include <stop_token> #include <stop_token>
#include <string> #include <string>
#include <thread> #include <thread>
@@ -19,11 +20,12 @@
#include <utils.hpp> #include <utils.hpp>
#define LCD_PORT "/dev/serial/by-id/usb-Raspberry_Pi_Pico_E6616407E37AA12F-if00" // tis a symlink, can also be just /dev/ttyACM0 #define LCD_PORT "/dev/serial/by-id/usb-Raspberry_Pi_Pico_E6616407E37AA12F-if00" // tis a symlink, can also be just /dev/ttyACM0
#define LCD_INTERVAL_MS 1000 #define LCD_INTERVAL_MS 500
#define LCD_CONTRAST 215 #define LCD_CONTRAST 215
std::chrono::milliseconds interval(LCD_INTERVAL_MS); /* these need to be global since we're talking to them from sighandler */
std::stop_source sigint; std::binary_semaphore sDisp{0}; // halts display func until we have sensor data
std::binary_semaphore sMain{0}; // halts the main thread until SIGINT
struct sensors_t { struct sensors_t {
std::array<std::string, 2> td; std::array<std::string, 2> td;
@@ -32,97 +34,117 @@ struct sensors_t {
mem_usage_t home; mem_usage_t home;
gpu_t gpu; gpu_t gpu;
cpu_t cpu; cpu_t cpu;
float hass_state = 0; float hass_state = 0.0f;
std::mutex mtx; // making sure the struct isnt accessed by multiple threads at once
}; };
void sighandler(int s) { void sighandler(int s) {
std::println("[Signal] got SIGINT, exiting..."); std::println("[Signal] got SIGINT/SIGTERM, exiting...");
sigint.request_stop(); sDisp.release();
sMain.release();
} }
void hass_thread(sensors_t *s, std::stop_token st) { void hass_thread(std::stop_token st, std::shared_ptr<sensors_t> s) {
std::println("[Thread] Starting hass_thread, pid {}", gettid()); std::println("[Thread] Starting hass_thread, pid {}", gettid());
hass_connect(); HomeAssistant pc_power("home.drath.win", "sensor.gniazdko_komputer_moc");
pc_power.connect();
while (!st.stop_requested()) { while (!st.stop_requested()) {
hass_poll(); pc_power.service();
s->hass_state = hass_get(); {
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // locks mutex for the lifetime of the scope, unlocks when it goes out of scope
std::lock_guard<std::mutex> lock(s->mtx);
s->hass_state = pc_power.state;
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
} }
hass_disconnect();
} }
void sensors_thread(sensors_t *s, std::stop_token st) { void sensors_thread(std::stop_token st, std::shared_ptr<sensors_t> s) {
std::println("[Thread] Starting sensors_thread, pid {}", gettid()); std::println("[Thread] Starting sensors_thread, pid {}, poll interval {} ms", gettid(), LCD_INTERVAL_MS);
/* find hwmon paths from pci addresses */
cpu_hwmon_t cpu_hwmon = detectCpuHwmon("0000:00:18.3"); cpu_hwmon_t cpu_hwmon = detectCpuHwmon("0000:00:18.3");
std::string gpu_hwmon = detectGpuHwmon("0000:08:00.0"); std::string gpu_hwmon = detectGpuHwmon("0000:08:00.0");
while (!st.stop_requested()) { while (!st.stop_requested()) {
auto start = std::chrono::steady_clock::now(); auto start = std::chrono::steady_clock::now();
s->td = getTimeDate(); {
s->loadavg = getAvgs(); std::lock_guard<std::mutex> lock(s->mtx); // will unlock when it goes out of scope, this is why this whole thing is in braces
s->ram = getRam(); s->td = getTimeDate();
s->home = getDisk("/home/drath"); s->loadavg = getAvgs();
s->cpu = getCpu(cpu_hwmon); s->ram = getRam();
s->gpu = getGpu(gpu_hwmon); s->home = getDisk("/home/drath");
s->cpu = getCpu(cpu_hwmon);
s->gpu = getGpu(gpu_hwmon);
}
// std::print("[Sensors] took {} microseconds \r", std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start).count()); // std::println("[Sensors] took {} microseconds", std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start).count());
// std::cout << std::flush; sDisp.release(); // unlocks display loop
std::this_thread::sleep_until(start + interval); std::this_thread::sleep_until(start + std::chrono::milliseconds(LCD_INTERVAL_MS));
} }
} }
void display_thread(sensors_t *s, std::stop_token st) { void display_thread(std::stop_token st, std::shared_ptr<sensors_t> s) {
std::println("[Thread] Starting display_thread, pid {}", gettid()); std::println("[Thread] Starting display_thread, pid {}", gettid());
LCDDisplay lcd(LCD_PORT); LCDDisplay lcd(LCD_PORT);
lcd.setCustomChar(0, {16, 6, 9, 8, 8, 9, 6, 0}); // celcius
std::println("[Chrono] Running in daemon mode, {} ms interval", LCD_INTERVAL_MS);
lcd.setContrast(LCD_CONTRAST); lcd.setContrast(LCD_CONTRAST);
lcd.setBacklight(true); lcd.setBacklight(true);
lcd.clear(); lcd.setCustomChar(0, {16, 6, 9, 8, 8, 9, 6, 0}); // celcius
while (!st.stop_requested()) { while (!st.stop_requested()) {
auto start = std::chrono::steady_clock::now(); sDisp.acquire(); // holds the loop until sensor data is ready
std::array<std::string, 4> lines; {
std::lock_guard<std::mutex> lock(s->mtx);
auto gpu_temps = (s->gpu.hotspot_temp) ? "/" + std::to_string(s->gpu.hotspot_temp) : ""; auto gpu_temps = (s->gpu.hotspot_temp) ? "/" + std::to_string(s->gpu.hotspot_temp) : "";
gpu_temps += (s->gpu.mem_temp) ? "/" + std::to_string(s->gpu.mem_temp) : ""; gpu_temps += (s->gpu.mem_temp) ? "/" + std::to_string(s->gpu.mem_temp) : "";
lcd.writeBuf(0, 0, pad(s->td[1], 11, true) + " " + s->td[0] + lcd.bar(1, s->gpu.core_usage / 100.0) + pad(s->loadavg, 17)); lcd.writeBuf(0, 0, pad(s->td[1], 11, true) + " " + s->td[0] + lcd.bar(1, s->gpu.core_usage / 100.0) + pad(s->loadavg, 17));
lcd.writeBuf(1, 0, pad(std::to_string(s->cpu.tctl) + "/" + std::to_string(s->cpu.tccd1) + lcd.cc[0], 8, true)); lcd.writeBuf(1, 0, pad(std::to_string(s->cpu.tctl) + "/" + std::to_string(s->cpu.tccd1) + lcd.cc[0], 8, true));
lcd.writeBuf(1, 8, pad(pBytes(s->ram.used, true) + "B", 7, true)); lcd.writeBuf(1, 8, pad(pBytes(s->ram.used, true) + "B", 7, true));
lcd.writeBuf(1, 16, pad(pNum(s->hass_state) + "W", 4)); lcd.writeBuf(1, 16, pad(pNum(s->hass_state) + "W", 4));
lcd.writeBuf(1, 22, pad(pBytes(s->gpu.vram_used) + "B", 7)); lcd.writeBuf(1, 22, pad(pBytes(s->gpu.vram_used) + "B", 7));
lcd.writeBuf(1, 29, pad(std::to_string(s->gpu.edge_temp) + gpu_temps + lcd.cc[0], 11)); lcd.writeBuf(1, 29, pad(std::to_string(s->gpu.edge_temp) + gpu_temps + lcd.cc[0], 11));
lcd.writeBuf(2, 0, pad(pNum(s->cpu.ptotal, 1) + "W", 8, true)); lcd.writeBuf(2, 0, pad(pNum(s->cpu.ptotal, 1) + "W", 8, true));
lcd.writeBuf(2, 14, "home:" + pad(pBytes(s->home.free), 5)); lcd.writeBuf(2, 8, "home:" + pad(pBytes(s->home.free), 5));
lcd.writeBuf(2, 25, pad(std::to_string(s->gpu.fan_speed), 4) + "R"); lcd.writeBuf(2, 20, pad(std::to_string(s->gpu.fan_pwm) + "%", 4));
// std::println("{}", s->gpu.fan_speed); lcd.writeBuf(2, 25, pad(std::to_string(s->gpu.fan_speed), 4) + "R");
lcd.writeBuf(2, 31, pad(std::to_string(s->gpu.power_avg) + "/" + std::to_string(s->gpu.power_cap) + "W", 9)); lcd.writeBuf(2, 31, 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, 3) + "V", 7, true)); lcd.writeBuf(3, 0, pad(pNum(s->cpu.vcore, 3) + "V", 7, true));
lcd.writeBuf(3, 7, std::to_string(s->cpu.avg_freq) + "MHz"); lcd.writeBuf(3, 7, std::to_string(s->cpu.avg_freq) + "MHz");
lcd.writeBuf(3, 21, pad(std::to_string(s->gpu.core_clock) + "/" + std::to_string(s->gpu.mem_clock) + "MHz ", 13)); lcd.writeBuf(3, 21, pad(std::to_string(s->gpu.core_clock) + "/" + std::to_string(s->gpu.mem_clock) + "MHz ", 13));
lcd.writeBuf(3, 34, pad(pNum(s->gpu.vcore, 3) + "Vabscd", 5)); lcd.writeBuf(3, 34, pad(pNum(s->gpu.vcore, 3) + "V", 5));
}
lcd.flushBuffer(); lcd.flushBuf();
std::this_thread::sleep_until(start + interval);
} }
lcd.clearBuf();
lcd.writeBuf(1, 10, "linuxSmartie closed");
// lcd.flushBuf();
} }
int main(int argc, char *argv[]) { int main(int argc, char* argv[]) {
signal(SIGINT, sighandler); std::signal(SIGINT, sighandler);
std::signal(SIGTERM, sighandler);
std::println("[Thread] Main thread, pid {}", gettid());
sensors_t sensors; std::shared_ptr<sensors_t> pSensors = std::make_shared<sensors_t>();
std::jthread producer(sensors_thread, &sensors, sigint.get_token()); std::jthread disp(display_thread, pSensors);
std::jthread hass(hass_thread, &sensors, sigint.get_token()); std::jthread hass(hass_thread, pSensors);
std::jthread sens(sensors_thread, pSensors);
display_thread(&sensors, sigint.get_token()); // halt main thread until we trigger sighandler
sMain.acquire();
// main thread resumed, tell workers to stop
hass.request_stop();
sens.request_stop();
disp.request_stop();
return 0; return 0;
} }