blob: 5f48674d0e64bd570108e6335a934918a4428fb7 [file] [log] [blame]
#pragma once
#include "Utils.hpp"
#include <Thresholds.hpp>
#include <boost/container/flat_map.hpp>
#include <filesystem>
#include <fstream>
#include <gpiod.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sensor.hpp>
class CPUSensor : public Sensor
{
public:
CPUSensor(const std::string& path, const std::string& objectType,
sdbusplus::asio::object_server& objectServer,
std::shared_ptr<sdbusplus::asio::connection>& conn,
boost::asio::io_service& io, const std::string& sensorName,
std::vector<thresholds::Threshold>&& thresholds,
const std::string& configuration, int cpuId, bool show,
double dtsOffset);
~CPUSensor();
static constexpr unsigned int sensorScaleFactor = 1000;
static constexpr unsigned int sensorPollMs = 1000;
static constexpr size_t warnAfterErrorCount = 10;
static constexpr double maxReading = 127;
static constexpr double minReading = -128;
static constexpr const char* labelTcontrol = "Tcontrol";
private:
sdbusplus::asio::object_server& objServer;
boost::asio::posix::stream_descriptor inputDev;
boost::asio::deadline_timer waitTimer;
boost::asio::streambuf readBuf;
std::string nameTcontrol;
std::string path;
double privTcontrol;
double dtsOffset;
bool show;
int errCount;
void setupRead(void);
void handleResponse(const boost::system::error_code& err);
void checkThresholds(void) override;
};
extern boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>>
gCpuSensors;
// this is added to cpusensor.hpp to avoid having every sensor have to link
// against libgpiod, if another sensor needs it we may move it to utils
inline bool hostIsPresent(size_t gpioNum)
{
static boost::container::flat_map<size_t, bool> cpuPresence;
auto findIndex = cpuPresence.find(gpioNum);
if (findIndex != cpuPresence.end())
{
return findIndex->second;
}
constexpr size_t sgpioBase = 232;
// check if sysfs has device
bool sysfs = std::filesystem::exists(gpioPath + std::string("gpio") +
std::to_string(gpioNum));
// todo: delete this when we remove all sysfs code
if (sysfs)
{
// close it, we'll reopen it at the end
std::ofstream unexport(gpioPath + std::string("unexport"));
if (unexport.good())
{
unexport << gpioNum;
}
else
{
std::cerr << "Error cleaning up sysfs device\n";
}
}
size_t chipNum = (gpioNum - sgpioBase) / 8;
size_t index = (gpioNum - sgpioBase) % 8;
gpiod::chip chip("gpiochip" + std::to_string(chipNum));
auto line = chip.get_line(index);
if (!line)
{
std::cerr << "Error requesting gpio\n";
return true;
}
bool resp = true;
try
{
line.request({"adcsensor", gpiod::line_request::DIRECTION_INPUT, 0});
resp = !line.get_value();
}
catch (std::system_error&)
{
std::cerr << "Error reading gpio\n";
return true;
}
// todo: delete this when we remove all sysfs code
if (sysfs)
{
// reopen it
std::ofstream populate(gpioPath + std::string("export"));
if (populate.good())
{
populate << gpioNum;
}
else
{
std::cerr << "Error cleaning up sysfs device\n";
}
}
cpuPresence[gpioNum] = resp;
return resp;
}