blob: 45348c61c59b852c9c0f8b4c9103883ac7aac6e7 [file] [log] [blame]
#include "tlbmc/sensors/shared_mem_based_sensor.h"
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include "google/protobuf/duration.pb.h"
#include "absl/functional/any_invocable.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/substitute.h"
#include "boost/asio.hpp" // NOLINT: boost::asio is commonly used in BMC
#include "boost/asio/random_access_file.hpp" // NOLINT: boost::asio is commonly used in BMC
#include "boost/filesystem.hpp" // NOLINT: boost::filesystem is commonly used in BMC
#include "boost/filesystem/operations.hpp" // NOLINT: boost::filesystem is commonly used in BMC
#include "boost/system/detail/error_code.hpp" // NOLINT: boost::asio is commonly used in BMC
// NOLINTNEXTLINE: keep this so BUILD file will keep liburing
#include "liburing.h" // IWYU pragma: keep
#include "entity_common_config.pb.h"
#include "i2c_common_config.pb.h"
#include "reading_range_config.pb.h"
#include "shared_mem_sensor_config.pb.h"
#include "threshold_config.pb.h"
#include "tlbmc/hal/shared_mem/server.h"
#include "resource.pb.h"
#include "sensor.pb.h"
#include "tlbmc/sensors/sensor.h"
#include "tlbmc/time/time.h"
namespace milotic_tlbmc {
absl::StatusOr<std::shared_ptr<Sensor>> SharedMemBasedSensor::Create(
const SharedMemSensorConfig& config,
const std::shared_ptr<boost::asio::io_context>& io_context,
std::optional<NotificationCb> on_batch_notify) {
return std::make_shared<SharedMemBasedSensor>(
Token(), config.type(), config.unit(),
// the sensor name rendering has a logic to trim a prefix before the first
// "_"(which comes from the dbus sensor name convention). Add a prefix to
// ensure the real name in redfish response is not partially trimmed.
absl::StrCat("sharedmem_", config.name()), config.entity_common_config(),
config.thresholds(), io_context, on_batch_notify);
}
SharedMemBasedSensor::SharedMemBasedSensor(
Token token, SharedMemSensorType sensor_type, SensorUnit sensor_unit,
const std::string& sensor_name,
const EntityCommonConfig& entity_common_config,
const ThresholdConfigs& threshold_configs,
const std::shared_ptr<boost::asio::io_context>& io_context,
std::optional<NotificationCb> on_batch_notify)
: Sensor(CreateStaticAttributes(sensor_name, sensor_unit,
/*i2c_common_config=*/{},
entity_common_config, threshold_configs,
/*reading_range_configs=*/{}),
on_batch_notify),
io_context_(io_context),
sensor_type_(sensor_type),
sensor_name_(sensor_name),
board_config_name_(entity_common_config.board_config_name()) {}
void SharedMemBasedSensor::RefreshOnceAsync(
absl::AnyInvocable<void(const std::shared_ptr<const SensorValue>&)>
callback) {
std::weak_ptr<SharedMemBasedSensor> self = shared_from_this();
boost::asio::post(*io_context_, [self(std::move(self)),
callback(std::move(callback))]() mutable {
std::shared_ptr<SharedMemBasedSensor> sensor = self.lock();
if (!sensor) {
LOG(WARNING) << "Sensor is destroyed; cancel the refresh.";
return;
}
// Get the sensor value from the shared memory.
auto sensor_value =
milotic_tlbmc::SharedMemoryServer::GetInstance().ReadSensorValue(
sensor->sensor_name_);
if (!sensor_value.ok()) {
State state;
state.set_status(STATUS_STALE);
state.set_status_message(absl::Substitute(
"Failed to read sensor value from shared memory: $0 with error: $1",
sensor->sensor_name_, sensor_value.status().message()));
sensor->UpdateState(std::move(state));
if (callback) {
callback(sensor->GetSensorData());
}
LOG(INFO) << "SharedMemBasedSensor::RefreshOnceAsync failed: "
<< sensor->sensor_name_ << " " << sensor_value.status();
return;
}
SensorValue sensor_data;
// milliseconds to timestamp
*sensor_data.mutable_timestamp() =
MilliSecondsToTimestamp(sensor_value->second);
sensor_data.set_reading(static_cast<double>(sensor_value->first));
LOG(INFO) << "SharedMemBasedSensor::RefreshOnceAsync success: "
<< sensor->sensor_name_ << " " << sensor_data.reading();
sensor->StoreSensorData(
std::make_shared<const SensorValue>(std::move(sensor_data)));
State state;
state.set_status(STATUS_READY);
sensor->UpdateState(std::move(state));
if (callback) {
callback(sensor->GetSensorData());
}
});
}
} // namespace milotic_tlbmc