inital commit
This commit is contained in:
commit
5dfdfce745
17
CMakeLists.txt
Normal file
17
CMakeLists.txt
Normal 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
103
ipmi.cpp
Normal 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
13
ipmi.h
Normal 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
118
main.cpp
Normal 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
15
sensor.h
Normal 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;}
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user