From 5dfdfce74504ac1ecc793fef47b2e8facd3ce825 Mon Sep 17 00:00:00 2001 From: uvos Date: Tue, 2 May 2023 10:13:45 +0200 Subject: [PATCH] inital commit --- CMakeLists.txt | 17 +++++++ ipmi.cpp | 103 ++++++++++++++++++++++++++++++++++++++++++ ipmi.h | 13 ++++++ main.cpp | 118 +++++++++++++++++++++++++++++++++++++++++++++++++ sensor.h | 15 +++++++ 5 files changed, 266 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 ipmi.cpp create mode 100644 ipmi.h create mode 100644 main.cpp create mode 100644 sensor.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ac7d40a --- /dev/null +++ b/CMakeLists.txt @@ -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) + diff --git a/ipmi.cpp b/ipmi.cpp new file mode 100644 index 0000000..8fd1e9c --- /dev/null +++ b/ipmi.cpp @@ -0,0 +1,103 @@ +#include "ipmi.h" +#include +#include + +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& 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& 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(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 "< +#include +#include + +#include "sensor.h" + +Sensor ipmi_read_sensor_from_ctx(ipmi_monitoring_ctx_t ctx); + +bool ipmi_fill_sensor_ids(std::vector& sensors, ipmi_monitoring_ctx_t ctx, struct ipmi_monitoring_ipmi_config* config); + +bool ipmi_update_sensors(std::vector& sensors, ipmi_monitoring_ctx_t ctx, struct ipmi_monitoring_ipmi_config* config); + +ipmi_monitoring_ctx_t init_ipmi_monitoring(); diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..c631445 --- /dev/null +++ b/main.cpp @@ -0,0 +1,118 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "ipmi.h" + +std::vector lm_get_chips(const std::string& match) +{ + std::vector 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 lm_get_sensors(std::vector& chips) +{ + std::vector 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 " + <number<<' '<name<<": "<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 lm_chips = lm_get_chips("amdgpu-*"); + std::vector lmsensors = lm_get_sensors(lm_chips); + + for(const Sensor& sensor : lmsensors) + { + std::cout< 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< + +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;} +};