inital commit

This commit is contained in:
uvos 2023-05-02 10:13:45 +02:00
commit 5dfdfce745
5 changed files with 266 additions and 0 deletions

17
CMakeLists.txt Normal file
View File

@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 3.20)
project(ipmifan LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
find_package(Doxygen)
find_package(PkgConfig REQUIRED)
pkg_search_module(IPMI REQUIRED libipmimonitoring)
add_executable(${PROJECT_NAME} main.cpp ipmi.cpp)
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_compile_options(${PROJECT_NAME} PRIVATE "-Wall" "-O2" "-g" "-fno-strict-aliasing" "-Wfatal-errors" "-Wno-reorder")
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)

103
ipmi.cpp Normal file
View File

@ -0,0 +1,103 @@
#include "ipmi.h"
#include <algorithm>
#include <iostream>
static double ipmi_convert_sensor_reading(void *sensor_reading, int sensor_reading_type)
{
if(sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL)
return (double)(*((uint8_t *)sensor_reading));
else if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32)
return (double)(*((uint32_t *)sensor_reading));
else if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE)
return *((double *)sensor_reading);
return 0;
}
Sensor ipmi_read_sensor_from_ctx(ipmi_monitoring_ctx_t ctx)
{
Sensor sensor;
int record_id = ipmi_monitoring_sensor_read_record_id(ctx);
int reading_type = ipmi_monitoring_sensor_read_sensor_reading_type(ctx);
char *name = ipmi_monitoring_sensor_read_sensor_name(ctx);
void *reading = ipmi_monitoring_sensor_read_sensor_reading(ctx);
if(record_id < 0 || reading_type < 0 || !name || !reading)
return sensor;
if(reading_type != IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32 &&
reading_type != IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE)
return sensor;
sensor.name.assign(name);
sensor.reading = ipmi_convert_sensor_reading(reading, reading_type);
sensor.id = record_id;
return sensor;
}
bool ipmi_fill_sensor_ids(std::vector<Sensor>& sensors, ipmi_monitoring_ctx_t ctx, struct ipmi_monitoring_ipmi_config* config)
{
unsigned int types[] = {IPMI_MONITORING_SENSOR_TYPE_TEMPERATURE};
unsigned int types_len = sizeof(types)/sizeof(types[0]);
int sensor_count = ipmi_monitoring_sensor_readings_by_sensor_type(ctx, NULL, config, 0, types, types_len, NULL, NULL);
for(int i = 0; i < sensor_count; ++i, ipmi_monitoring_sensor_iterator_next(ctx))
{
Sensor sensor = ipmi_read_sensor_from_ctx(ctx);
auto search = std::find(sensors.begin(), sensors.end(), sensor);
if(search != sensors.end())
*search = sensor;
}
for(Sensor& sensor : sensors)
{
if(sensor.id == 0 && sensor.chip == "IPMI")
return false;
}
return true;
}
bool ipmi_update_sensors(std::vector<Sensor>& sensors, ipmi_monitoring_ctx_t ctx, struct ipmi_monitoring_ipmi_config* config)
{
unsigned int *ids = new unsigned int[sensors.size()];
for(size_t i = 0; i < sensors.size(); ++i)
ids[i] = sensors[i].id;
int sensor_count = ipmi_monitoring_sensor_readings_by_record_id(ctx, NULL, config, 0, ids, sensors.size(), NULL, NULL);
delete[] ids;
if(sensor_count < static_cast<int>(sensors.size()))
return false;
for(int i = 0; i < sensor_count; ++i, ipmi_monitoring_sensor_iterator_next(ctx))
{
Sensor readsensor = ipmi_read_sensor_from_ctx(ctx);
for(Sensor& sensor : sensors)
{
if(sensor.id == readsensor.id)
sensor = readsensor;
}
}
return true;
}
ipmi_monitoring_ctx_t init_ipmi_monitoring()
{
int errnum;
int ret = ipmi_monitoring_init(/*IPMI_MONITORING_FLAGS_DEBUG*/ 0, &errnum);
if(ret < 0)
{
std::cerr<<"Could not init ipmi "<<ipmi_monitoring_ctx_strerror(errnum)<<'\n';
return NULL;
}
ipmi_monitoring_ctx_t ctx = ipmi_monitoring_ctx_create();
if(!ctx)
{
std::cerr<<"failed to create montioring context\n";
return NULL;
}
return ctx;
}

13
ipmi.h Normal file
View File

@ -0,0 +1,13 @@
#include <vector>
#include <string>
#include <ipmi_monitoring.h>
#include "sensor.h"
Sensor ipmi_read_sensor_from_ctx(ipmi_monitoring_ctx_t ctx);
bool ipmi_fill_sensor_ids(std::vector<Sensor>& sensors, ipmi_monitoring_ctx_t ctx, struct ipmi_monitoring_ipmi_config* config);
bool ipmi_update_sensors(std::vector<Sensor>& sensors, ipmi_monitoring_ctx_t ctx, struct ipmi_monitoring_ipmi_config* config);
ipmi_monitoring_ctx_t init_ipmi_monitoring();

118
main.cpp Normal file
View File

@ -0,0 +1,118 @@
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <unistd.h>
#include <sensors/sensors.h>
#include <sensors/error.h>
#include "ipmi.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_sensors(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;
}
int main (int argc, char **argv)
{
int ret = sensors_init(nullptr);
if(ret < 0)
{
std::cerr<<"Could not init lm_sensors\n";
}
std::vector<const sensors_chip_name*> lm_chips = lm_get_chips("amdgpu-*");
std::vector<Sensor> lmsensors = lm_get_sensors(lm_chips);
for(const Sensor& sensor : lmsensors)
{
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();
if(!ctx)
return 1;
if(!ipmi_fill_sensor_ids(sensors, ctx, &ipmi_config))
{
std::cout<<"could not get ids for all the required sensors\n";
return 1;
}
while(true)
{
ipmi_update_sensors(sensors, ctx, &ipmi_config);
std::cout<<sensors[0].reading<<std::endl;
sleep(1);
}
ipmi_monitoring_ctx_destroy(ctx);
sensors_cleanup();
return 0;
}

15
sensor.h Normal file
View File

@ -0,0 +1,15 @@
#include <string>
class Sensor
{
public:
std::string chip;
std::string name;
int id = 0;
double reading = 0;
public:
Sensor() = default;
Sensor(std::string chipI, std::string nameI, int idI = 0): name(nameI), chip(chipI), name(nameI), id(idI) {}
bool operator==(const Sensor& other) {return other.name == name && other.chip == chip;}
};