| #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 |