Older/Server/SystemUsage.cpp
2024-05-03 22:30:46 +08:00

97 lines
3.2 KiB
C++

#include "SystemUsage.h"
#include "BoostLog.h"
#include "NetworkUtility.h"
#include <boost/json/object.hpp>
#include <boost/json/serialize.hpp>
#include <fstream>
#include <sstream>
#include <sys/statvfs.h>
#include <sys/sysinfo.h>
SystemUsage::SystemUsage(boost::asio::io_context &ioContext, const std::string &accessToken)
: m_ioContext(ioContext), m_accessToken(accessToken) {
m_timer = std::make_shared<boost::asio::system_timer>(m_ioContext);
// LOG(info) << "access token: " << m_accessToken;
}
void SystemUsage::start() {
m_timer->expires_after(std::chrono::seconds(10));
m_timer->async_wait([this](const boost::system::error_code &error) {
if (error) {
LOG(error) << error.message();
return;
}
auto currentCpuStats = readCpuData();
int usage = 100.0f * cpuUsage(m_lastCpuStats, currentCpuStats);
publish("yuyun_cpu_usage", usage, "%", "CPU占用率");
publish("yuyun_disk_usage", static_cast<int>(100.0f * diskUsage("/")), "%", "磁盘占用率");
m_lastCpuStats = currentCpuStats;
start();
});
}
void SystemUsage::publish(const std::string_view &deviceName, float value, const std::string_view &unit,
const std::string_view &friendlyName) {
// LOG(info) << "cpu usage: " << usage << "%";
Http::Client http(m_ioContext, Http::Transparent);
std::ostringstream oss;
oss << "Bearer " << m_accessToken;
http.addRequestField(boost::beast::http::field::authorization, oss.str());
http.addRequestField(boost::beast::http::field::content_type, "application/json");
boost::json::object request;
request["state"] = value;
boost::json::object attributes;
attributes["unit_of_measurement"] = unit;
attributes["friendly_name"] = friendlyName;
request["attributes"] = std::move(attributes);
oss.str("");
oss << "/api/states/sensor." << deviceName;
boost::system::error_code error;
auto reply = http.post("iot.amass.fun", "80", oss.str(), boost::json::serialize(request), error);
if (error) {
LOG(error) << error.message();
}
}
SystemUsage::CpuStats SystemUsage::readCpuData() {
CpuStats result;
std::ifstream proc_stat("/proc/stat");
if (proc_stat.good()) {
std::string line;
getline(proc_stat, line);
unsigned int *stats_p = (unsigned int *)&result;
std::stringstream iss(line);
std::string cpu;
iss >> cpu;
while (iss >> *stats_p) {
stats_p++;
};
}
proc_stat.close();
return result;
}
float SystemUsage::cpuUsage(const CpuStats &first, const CpuStats &second) {
const float active_time = static_cast<float>(second.totalActive() - first.totalActive());
const float idle_time = static_cast<float>(second.totalIdle() - first.totalIdle());
const float total_time = active_time + idle_time;
return active_time / total_time;
}
float SystemUsage::diskUsage(const std::string &disk) {
struct statvfs diskData;
statvfs(disk.c_str(), &diskData);
auto total = diskData.f_blocks;
auto free = diskData.f_bfree;
auto diff = total - free;
float result = static_cast<float>(diff) / total;
return result;
}