sensor monitoring compleat, starting on fan control

This commit is contained in:
Carl Philipp Klemm 2023-05-02 10:52:56 +02:00
parent 5dfdfce745
commit 9c17bfe0bf
6 changed files with 130 additions and 70 deletions

View File

@ -9,7 +9,7 @@ find_package(Doxygen)
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
pkg_search_module(IPMI REQUIRED libipmimonitoring) pkg_search_module(IPMI REQUIRED libipmimonitoring)
add_executable(${PROJECT_NAME} main.cpp ipmi.cpp) add_executable(${PROJECT_NAME} main.cpp ipmi.cpp lm.cpp)
target_link_libraries(${PROJECT_NAME} ${IPMI_LINK_LIBRARIES} ${IPMIPOSIX_LINK_LIBRARIES} sensors) target_link_libraries(${PROJECT_NAME} ${IPMI_LINK_LIBRARIES} ${IPMIPOSIX_LINK_LIBRARIES} sensors)
target_include_directories(${PROJECT_NAME} PRIVATE ${IPMI_INCLUDE_DIRS} ${IPMIPOSIX_INCLUDE_DIRS}) target_include_directories(${PROJECT_NAME} PRIVATE ${IPMI_INCLUDE_DIRS} ${IPMIPOSIX_INCLUDE_DIRS})
target_compile_options(${PROJECT_NAME} PRIVATE "-Wall" "-O2" "-g" "-fno-strict-aliasing" "-Wfatal-errors" "-Wno-reorder") target_compile_options(${PROJECT_NAME} PRIVATE "-Wall" "-O2" "-g" "-fno-strict-aliasing" "-Wfatal-errors" "-Wno-reorder")

View File

@ -16,6 +16,7 @@ static double ipmi_convert_sensor_reading(void *sensor_reading, int sensor_readi
Sensor ipmi_read_sensor_from_ctx(ipmi_monitoring_ctx_t ctx) Sensor ipmi_read_sensor_from_ctx(ipmi_monitoring_ctx_t ctx)
{ {
Sensor sensor; Sensor sensor;
sensor.chip = "IPMI";
int record_id = ipmi_monitoring_sensor_read_record_id(ctx); int record_id = ipmi_monitoring_sensor_read_record_id(ctx);
int reading_type = ipmi_monitoring_sensor_read_sensor_reading_type(ctx); int reading_type = ipmi_monitoring_sensor_read_sensor_reading_type(ctx);
char *name = ipmi_monitoring_sensor_read_sensor_name(ctx); char *name = ipmi_monitoring_sensor_read_sensor_name(ctx);

63
lm.cpp Normal file
View File

@ -0,0 +1,63 @@
#include "lm.h"
std::vector<const sensors_chip_name*> lm_get_chips(const std::string& match)
{
std::vector<const sensors_chip_name*> out;
sensors_chip_name name_glob;
int ret = sensors_parse_chip_name(match.c_str(), &name_glob);
if(ret < 0)
{
std::cerr<<"could not parse chip name\n";
return out;
}
const sensors_chip_name* s_name;
int nr = 0;
do
{
s_name = sensors_get_detected_chips(&name_glob, &nr);
if(s_name)
out.push_back(s_name);
} while(s_name);
sensors_free_chip_name(&name_glob);
return out;
}
std::vector<Sensor> lm_get_temperatures(std::vector<const sensors_chip_name*>& chips)
{
std::vector<Sensor> out;
for(const sensors_chip_name* chip : chips)
{
int nr = 0;
const sensors_feature* feature;
while((feature = sensors_get_features(chip, &nr)))
{
if(feature->type != SENSORS_FEATURE_TEMP)
continue;
const sensors_subfeature* subfeature = sensors_get_subfeature(chip, feature, SENSORS_SUBFEATURE_TEMP_INPUT);
if(!subfeature)
{
std::cerr<<"could not read subfeature\n";
continue;
}
double val = 0;
int ret = sensors_get_value(chip, subfeature->number, &val);
if(ret < 0)
{
std::cerr<<"unable to read temperature for subfeature "
<<subfeature->number<<' '<<subfeature->name<<": "<<sensors_strerror(ret)<<'\n';
continue;
}
Sensor sensor;
sensor.name.assign(sensors_get_label(chip, feature));
sensor.id = subfeature->number;
sensor.reading = val;
out.push_back(sensor);
}
}
return out;
}

12
lm.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <vector>
#include <string>
#include <iostream>
#include <sensors/sensors.h>
#include <sensors/error.h>
#include "sensor.h"
std::vector<const sensors_chip_name*> lm_get_chips(const std::string& match);
std::vector<Sensor> lm_get_temperatures(std::vector<const sensors_chip_name*>& chips);

118
main.cpp
View File

@ -5,73 +5,71 @@
#include <unistd.h> #include <unistd.h>
#include <sensors/sensors.h> #include <sensors/sensors.h>
#include <sensors/error.h> #include <sensors/error.h>
#include <signal.h>
#include "ipmi.h" #include "ipmi.h"
#include "lm.h"
std::vector<const sensors_chip_name*> lm_get_chips(const std::string& match) sig_atomic_t running = true;
void sig_handler(int sig)
{ {
std::vector<const sensors_chip_name*> out; (void)sig;
running = false;
}
sensors_chip_name name_glob; std::vector<Sensor> gather_sensors(std::vector<Sensor>& ipmi_sensors, ipmi_monitoring_ctx_t ctx, std::vector<const sensors_chip_name*>& lm_chips)
int ret = sensors_parse_chip_name(match.c_str(), &name_glob); {
if(ret < 0) std::vector<Sensor> out;
struct ipmi_monitoring_ipmi_config ipmi_config = {};
ipmi_config.driver_type = IPMI_MONITORING_DRIVER_TYPE_OPENIPMI;
bool grabids = false;
for(Sensor& sensor : ipmi_sensors)
{ {
std::cerr<<"could not parse chip name\n"; if(sensor.id <= 0)
return out; {
grabids = true;
break;
}
} }
const sensors_chip_name* s_name; if(grabids)
int nr = 0;
do
{ {
s_name = sensors_get_detected_chips(&name_glob, &nr); if(!ipmi_fill_sensor_ids(ipmi_sensors, ctx, &ipmi_config))
if(s_name) {
out.push_back(s_name); std::cout<<"could not get ids for all the required sensors\n";
} while(s_name); return out;
sensors_free_chip_name(&name_glob); }
}
else
{
ipmi_update_sensors(ipmi_sensors, ctx, &ipmi_config);
}
out.insert(out.end(), ipmi_sensors.begin(), ipmi_sensors.end());
std::vector<Sensor> lm_sensors = lm_get_temperatures(lm_chips);
out.insert(out.end(), lm_sensors.begin(), lm_sensors.end());
return out; return out;
} }
std::vector<Sensor> lm_get_sensors(std::vector<const sensors_chip_name*>& chips) std::vector<double> get_fan_zones(const std::vector<Sensor>& sensors)
{ {
std::vector<Sensor> out; std::vector<double> out;
for(const sensors_chip_name* chip : chips) for(const Sensor& sensor : sensors)
{ std::cout<<sensor.chip<<' '<<sensor.name<<": "<<sensor.reading;
int nr = 0;
const sensors_feature* feature;
while((feature = sensors_get_features(chip, &nr)))
{
if(feature->type != SENSORS_FEATURE_TEMP)
continue;
const sensors_subfeature* subfeature = sensors_get_subfeature(chip, feature, SENSORS_SUBFEATURE_TEMP_INPUT);
if(!subfeature)
{
std::cerr<<"could not read subfeature\n";
continue;
}
double val = 0;
int ret = sensors_get_value(chip, subfeature->number, &val);
if(ret < 0)
{
std::cerr<<"unable to read temperature for subfeature "
<<subfeature->number<<' '<<subfeature->name<<": "<<sensors_strerror(ret)<<'\n';
continue;
}
Sensor sensor;
sensor.name.assign(sensors_get_label(chip, feature));
sensor.id = subfeature->number;
sensor.reading = val;
out.push_back(sensor);
}
}
return out; return out;
} }
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
signal(SIGABRT, sig_handler);
signal(SIGTERM, sig_handler);
signal(SIGHUP, sig_handler);
signal(SIGINT, sig_handler);
int ret = sensors_init(nullptr); int ret = sensors_init(nullptr);
if(ret < 0) if(ret < 0)
@ -80,34 +78,18 @@ int main (int argc, char **argv)
} }
std::vector<const sensors_chip_name*> lm_chips = lm_get_chips("amdgpu-*"); std::vector<const sensors_chip_name*> lm_chips = lm_get_chips("amdgpu-*");
std::vector<Sensor> lmsensors = lm_get_sensors(lm_chips); std::vector<Sensor> ipmi_sensors;
ipmi_sensors.push_back(Sensor("IPMI", "CPU Temp"));
for(const Sensor& sensor : lmsensors) ipmi_sensors.push_back(Sensor("IPMI", "System Temp"));
{
std::cout<<sensor.name<<": "<<sensor.reading<<'\n';
}
struct ipmi_monitoring_ipmi_config ipmi_config = {};
ipmi_config.driver_type = IPMI_MONITORING_DRIVER_TYPE_OPENIPMI;
std::vector<Sensor> sensors;
sensors.push_back(Sensor("CPU Temp"));
sensors.push_back(Sensor("System Temp"));
ipmi_monitoring_ctx_t ctx = init_ipmi_monitoring(); ipmi_monitoring_ctx_t ctx = init_ipmi_monitoring();
if(!ctx) if(!ctx)
return 1; return 1;
if(!ipmi_fill_sensor_ids(sensors, ctx, &ipmi_config)) while(running)
{ {
std::cout<<"could not get ids for all the required sensors\n"; std::vector<Sensor> sensors = gather_sensors(ipmi_sensors, ctx, lm_chips);
return 1; get_fan_zones(sensors);
}
while(true)
{
ipmi_update_sensors(sensors, ctx, &ipmi_config);
std::cout<<sensors[0].reading<<std::endl;
sleep(1); sleep(1);
} }

View File

@ -1,3 +1,5 @@
#pragma once
#include <string> #include <string>
class Sensor class Sensor
@ -10,6 +12,6 @@ public:
public: public:
Sensor() = default; Sensor() = default;
Sensor(std::string chipI, std::string nameI, int idI = 0): name(nameI), chip(chipI), name(nameI), id(idI) {} Sensor(std::string chipI, std::string nameI, int idI = 0): name(nameI), chip(chipI), id(idI) {}
bool operator==(const Sensor& other) {return other.name == name && other.chip == chip;} bool operator==(const Sensor& other) {return other.name == name && other.chip == chip;}
}; };