make it a class
This commit is contained in:
@@ -1,14 +1,36 @@
|
|||||||
#ifndef APP_HPP
|
#ifndef APP_HPP
|
||||||
#define APP_HPP
|
#define APP_HPP
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
#include <gpu.hpp>
|
#include <gpu.hpp>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <semaphore>
|
#include <semaphore>
|
||||||
#include <stop_token>
|
#include <stop_token>
|
||||||
#include <sys.hpp>
|
#include <sys.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
class Application {
|
class Application {
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Config {
|
||||||
|
uint16_t lcd_interval_ms = 500;
|
||||||
|
uint8_t lcd_contrast = 215;
|
||||||
|
|
||||||
|
std::string lcd_port;
|
||||||
|
std::string cpu_pciaddr = "0000:00:18.3";
|
||||||
|
std::string gpu_pciaddr = "0000:0b:00.0";
|
||||||
|
std::string sys_sensor = "nct6775.656";
|
||||||
|
std::string sys_ifname = "enp4s0f0";
|
||||||
|
std::string home_dir = "/home/drath";
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit Application(const Config& config);
|
||||||
|
~Application();
|
||||||
|
void Run();
|
||||||
|
|
||||||
|
private:
|
||||||
struct Sensors {
|
struct Sensors {
|
||||||
sys::TimeDate td;
|
sys::TimeDate td;
|
||||||
double avg[3] = {0.0f};
|
double avg[3] = {0.0f};
|
||||||
@@ -22,29 +44,21 @@ class Application {
|
|||||||
std::mutex mtx; // making sure the struct isnt accessed by multiple threads at once
|
std::mutex mtx; // making sure the struct isnt accessed by multiple threads at once
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Semaphores {
|
struct Control {
|
||||||
inline static std::binary_semaphore display{0};
|
std::binary_semaphore display{0};
|
||||||
inline static std::binary_semaphore main{0};
|
std::binary_semaphore main{0};
|
||||||
|
std::atomic_bool quit{false};
|
||||||
|
std::stop_source stop;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string lcd_port;
|
Config m_config; // m_ is member variable
|
||||||
uint16_t lcd_interval_ms = 500;
|
Control m_control;
|
||||||
uint8_t lcd_contrast = 215;
|
|
||||||
|
|
||||||
std::string cpu_pciaddr = "0000:00:18.3";
|
|
||||||
std::string gpu_pciaddr = "0000:0b:00.0";
|
|
||||||
std::string sys_sensor = "nct6775.656";
|
|
||||||
std::string sys_ifname = "enp4s0f0";
|
|
||||||
std::string home_dir = "/home/drath";
|
|
||||||
|
|
||||||
|
static Application* s_instance;
|
||||||
static void signalHandler(int);
|
static void signalHandler(int);
|
||||||
static void hassThread(const std::stop_token& st, Sensors& s);
|
static void hassThread(const std::stop_token& st, Sensors& s);
|
||||||
static void sensorsThread(const std::stop_token& st, Sensors& s);
|
void sensorsThread(const std::stop_token& st, Sensors& s);
|
||||||
static void displayThread(const std::stop_token& st, Sensors& s);
|
void displayThread(const std::stop_token& st, Sensors& s);
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Application(const std::string& display_port);
|
|
||||||
void Run();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
15
main.cpp
15
main.cpp
@@ -1,7 +1,18 @@
|
|||||||
#include <app.hpp>
|
#include <app.hpp>
|
||||||
// put app in a class w a constructor for all the basic params
|
|
||||||
int main() {
|
int main() {
|
||||||
Application app("/dev/serial/by-id/usb-Raspberry_Pi_Pico_E6616407E37AA12F-if00"); // tis a symlink, can also be just /dev/ttyACM0)
|
Application::Config config;
|
||||||
|
|
||||||
|
config.lcd_port = "/dev/serial/by-id/usb-Raspberry_Pi_Pico_E6616407E37AA12F-if00";
|
||||||
|
config.lcd_interval_ms = 500;
|
||||||
|
config.lcd_contrast = 215;
|
||||||
|
config.cpu_pciaddr = "0000:00:18.3";
|
||||||
|
config.gpu_pciaddr = "0000:0b:00.0";
|
||||||
|
config.sys_sensor = "nct6775.656";
|
||||||
|
config.sys_ifname = "enp4s0f0";
|
||||||
|
config.home_dir = "/home/drath";
|
||||||
|
|
||||||
|
Application app(config); // tis a symlink, can also be just /dev/ttyACM0)
|
||||||
app.Run();
|
app.Run();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
61
src/app.cpp
61
src/app.cpp
@@ -15,13 +15,12 @@
|
|||||||
#include <utils.hpp>
|
#include <utils.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// std::binary_semaphore Application::Semaphores::main{0};
|
Application* Application::s_instance = nullptr;
|
||||||
// std::binary_semaphore Application::Semaphores::display{0};
|
|
||||||
|
|
||||||
void Application::signalHandler(int) {
|
void Application::signalHandler(int) {
|
||||||
applog(LOG::WRN, "got SIGINT/SIGTERM, exiting...");
|
applog(LOG::WRN, "got SIGINT/SIGTERM, exiting...");
|
||||||
this->Semaphores::main.release();
|
if (s_instance)
|
||||||
this->Semaphores::display.release();
|
s_instance->m_control.quit.store(true, std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::hassThread(const std::stop_token& st, Sensors& s) {
|
void Application::hassThread(const std::stop_token& st, Sensors& s) {
|
||||||
@@ -40,11 +39,11 @@ void Application::hassThread(const std::stop_token& st, Sensors& s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Application::sensorsThread(const std::stop_token& st, Sensors& s) {
|
void Application::sensorsThread(const std::stop_token& st, Sensors& s) {
|
||||||
applog(LOG::START, "Thread started, poll interval {} ms", lcd_interval_ms);
|
applog(LOG::START, "Thread started, poll interval {} ms", m_config.lcd_interval_ms);
|
||||||
cpu::detectHwmon(&s.cpu, cpu_pciaddr);
|
cpu::detectHwmon(&s.cpu, m_config.cpu_pciaddr);
|
||||||
gpu::detectHwmon(&s.gpu, gpu_pciaddr);
|
gpu::detectHwmon(&s.gpu, m_config.gpu_pciaddr);
|
||||||
sys::detectHwmon(&s.sys, sys_sensor);
|
sys::detectHwmon(&s.sys, m_config.sys_sensor);
|
||||||
s.home.mountpoint = home_dir;
|
s.home.mountpoint = m_config.home_dir;
|
||||||
|
|
||||||
while (!st.stop_requested()) {
|
while (!st.stop_requested()) {
|
||||||
auto start = std::chrono::steady_clock::now();
|
auto start = std::chrono::steady_clock::now();
|
||||||
@@ -55,25 +54,27 @@ void Application::sensorsThread(const std::stop_token& st, Sensors& s) {
|
|||||||
getloadavg(s.avg, 3);
|
getloadavg(s.avg, 3);
|
||||||
sys::getRam(&s.ram);
|
sys::getRam(&s.ram);
|
||||||
sys::getDisk(&s.home);
|
sys::getDisk(&s.home);
|
||||||
sys::getNetwork(&s.net, sys_ifname);
|
sys::getNetwork(&s.net, m_config.sys_ifname);
|
||||||
sys::updateSensors(&s.sys);
|
sys::updateSensors(&s.sys);
|
||||||
cpu::update(&s.cpu);
|
cpu::update(&s.cpu);
|
||||||
gpu::update(&s.gpu);
|
gpu::update(&s.gpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
// log(LOG::DBG, "took {} microseconds", std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start).count());
|
// log(LOG::DBG, "took {} microseconds", std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start).count());
|
||||||
this->Semaphores::display.release(); // unlocks display loop
|
m_control.display.release(); // unlocks display loop
|
||||||
std::this_thread::sleep_until(start + std::chrono::milliseconds(lcd_interval_ms));
|
std::this_thread::sleep_until(start + std::chrono::milliseconds(m_config.lcd_interval_ms));
|
||||||
}
|
}
|
||||||
|
applog(LOG::INF, "Stopped thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::displayThread(const std::stop_token& st, Sensors& s) {
|
void Application::displayThread(const std::stop_token& st, Sensors& s) {
|
||||||
|
std::stop_callback cb(st, [&] { m_control.display.release(); });
|
||||||
applog(LOG::START, "Thread started");
|
applog(LOG::START, "Thread started");
|
||||||
// init internal variables of LCDDisplay class
|
// init internal variables of LCDDisplay class
|
||||||
LCDDisplay lcd(lcd_port);
|
LCDDisplay lcd(m_config.lcd_port);
|
||||||
|
|
||||||
// basic lcd setup
|
// basic lcd setup
|
||||||
lcd.setContrast(lcd_contrast);
|
lcd.setContrast(m_config.lcd_contrast);
|
||||||
lcd.setBacklight(true);
|
lcd.setBacklight(true);
|
||||||
lcd.setCustomChar(0, {16, 6, 9, 8, 8, 9, 6, 0}); // celcius
|
lcd.setCustomChar(0, {16, 6, 9, 8, 8, 9, 6, 0}); // celcius
|
||||||
lcd.setCustomChar(1, {0, 0, 4, 10, 10, 17, 31, 0}); // delta
|
lcd.setCustomChar(1, {0, 0, 4, 10, 10, 17, 31, 0}); // delta
|
||||||
@@ -88,7 +89,8 @@ void Application::displayThread(const std::stop_token& st, Sensors& s) {
|
|||||||
|
|
||||||
// actual main display loop
|
// actual main display loop
|
||||||
while (!st.stop_requested()) {
|
while (!st.stop_requested()) {
|
||||||
this->Semaphores::display.acquire(); // holds the loop until sensor data is ready
|
m_control.display.try_acquire_for(std::chrono::milliseconds(static_cast<int>(m_config.lcd_interval_ms * 1.25))); // holds the loop until sensor data is ready, max 1.25x of the loop time
|
||||||
|
if (st.stop_requested()) break; // needed, otherwise it wont quit correctly
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(s.mtx);
|
std::lock_guard<std::mutex> lock(s.mtx);
|
||||||
|
|
||||||
@@ -137,26 +139,37 @@ void Application::displayThread(const std::stop_token& st, Sensors& s) {
|
|||||||
lcd.flushBuf();
|
lcd.flushBuf();
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::Application(const std::string& display_port) {
|
Application::Application(const Config& config) : m_config(config) {
|
||||||
this->lcd_port = display_port;
|
}
|
||||||
|
|
||||||
|
Application::~Application() {
|
||||||
|
applog(LOG::START, "Application stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::Run() {
|
void Application::Run() {
|
||||||
applog(LOG::START, "Application started");
|
applog(LOG::START, "Application started");
|
||||||
std::signal(SIGINT, signalHandler);
|
s_instance = this;
|
||||||
std::signal(SIGTERM, signalHandler);
|
std::signal(SIGINT, &Application::signalHandler);
|
||||||
|
std::signal(SIGTERM, &Application::signalHandler);
|
||||||
|
|
||||||
{
|
{
|
||||||
Sensors sensors;
|
Sensors sensors;
|
||||||
std::vector<std::jthread> threads;
|
std::vector<std::jthread> threads;
|
||||||
|
|
||||||
for (std::function<void(std::stop_token st, Sensors & s)> funcs[] = {displayThread, sensorsThread, hassThread};
|
std::function<void(std::stop_token, Sensors&)> funcs[] = {
|
||||||
auto& f : funcs)
|
[this](const std::stop_token& st, Sensors& s) { displayThread(st, s); },
|
||||||
{
|
[this](const std::stop_token& st, Sensors& s) { sensorsThread(st, s); },
|
||||||
|
[this](const std::stop_token& st, Sensors& s) { hassThread(st, s); },
|
||||||
|
};
|
||||||
|
|
||||||
|
// start threads in order
|
||||||
|
for (auto& f : funcs) {
|
||||||
threads.emplace_back(f, std::ref(sensors)); // params: function, stop_token (implied), pointer to sensor struct
|
threads.emplace_back(f, std::ref(sensors)); // params: function, stop_token (implied), pointer to sensor struct
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10)); // start threads with delay so displayThread can quit the app if theres no lcd
|
std::this_thread::sleep_for(std::chrono::milliseconds(10)); // start threads with delay so displayThread can quit the app if theres no lcd
|
||||||
}
|
}
|
||||||
|
|
||||||
this->Semaphores::main.acquire();
|
// hold until signal recieved
|
||||||
|
while (!m_control.quit.load(std::memory_order_relaxed))
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(10)); // ugly
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user