| #include "tlbmc/sensors/nic_sensor.h" |
| |
| #include <chrono> // NOLINT: chrono is commonly used in BMC |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <utility> |
| |
| #include "absl/functional/any_invocable.h" |
| #include "absl/log/log.h" |
| #include "absl/status/statusor.h" |
| #include "absl/strings/str_cat.h" |
| #include "tlbmc/hal/nic_veeprom/interface.h" |
| #include "tlbmc/sensors/sensor.h" |
| |
| namespace milotic_tlbmc { |
| |
| absl::StatusOr<std::shared_ptr<NicSensor>> NicSensor::Create( |
| const std::string& sensor_name, |
| nic_veeprom::NicTelemetryName telemetry_name, SensorUnit sensor_unit, |
| const EntityCommonConfig& entity_common_config, |
| const ThresholdConfigs& threshold_configs, |
| const ReadingRangeConfigs& reading_range_configs, |
| const std::shared_ptr<boost::asio::io_context>& io_context, |
| const nic_veeprom::Accessor& accessor, |
| std::optional<NotificationCb> on_batch_notify) { |
| return std::make_shared<NicSensor>(Token(), sensor_name, telemetry_name, |
| sensor_unit, entity_common_config, |
| threshold_configs, reading_range_configs, |
| io_context, accessor, on_batch_notify); |
| } |
| |
| NicSensor::NicSensor(Token token, const std::string& sensor_name, |
| nic_veeprom::NicTelemetryName telemetry_name, |
| SensorUnit sensor_unit, |
| const EntityCommonConfig& entity_common_config, |
| const ThresholdConfigs& threshold_configs, |
| const ReadingRangeConfigs& reading_range_configs, |
| const std::shared_ptr<boost::asio::io_context>& io_context, |
| const nic_veeprom::Accessor& accessor, |
| std::optional<NotificationCb> on_batch_notify) |
| : Sensor(CreateStaticAttributes(sensor_name, sensor_unit, |
| /*i2c_common_config=*/{}, |
| entity_common_config, reading_range_configs, |
| /*reading_transform_config=*/{}), |
| threshold_configs, on_batch_notify), |
| telemetry_name_(telemetry_name), |
| sensor_unit_(sensor_unit), |
| io_context_(io_context), |
| accessor_(accessor) {} |
| |
| void NicSensor::RefreshOnceAsync( |
| absl::AnyInvocable<void(const std::shared_ptr<const SensorValue>&)> |
| callback) { |
| std::weak_ptr<NicSensor> self = shared_from_this(); |
| boost::asio::post(*io_context_, [self(std::move(self)), |
| callback(std::move(callback))]() mutable { |
| std::shared_ptr<NicSensor> sensor = self.lock(); |
| if (!sensor) { |
| LOG(WARNING) << "Sensor is destroyed; cancel the refresh."; |
| return; |
| } |
| std::chrono::steady_clock::time_point last_refresh_start_time = |
| sensor->GetLastRefreshStartTime(); |
| if (last_refresh_start_time != |
| std::chrono::steady_clock::time_point::min()) { |
| sensor->UpdateSoftwarePollingStartMetrics( |
| std::chrono::steady_clock::now() - last_refresh_start_time); |
| } |
| sensor->SetLastRefreshStartTime(std::chrono::steady_clock::now()); |
| |
| // Get the sensor value |
| absl::StatusOr<const std::shared_ptr<const SensorValue>> sensor_value = |
| sensor->GetSensorValue(); |
| |
| if (!sensor_value.ok()) { |
| State state; |
| state.set_status(STATUS_STALE); |
| state.set_status_message( |
| absl::StrCat("Failed to read sensor value with error: ", |
| sensor_value.status().message())); |
| sensor->UpdateState(std::move(state)); |
| if (callback) { |
| callback(sensor->GetSensorData()); |
| } |
| } else { |
| sensor->StoreSensorData(*sensor_value); |
| State state; |
| state.set_status(STATUS_READY); |
| sensor->UpdateState(std::move(state)); |
| |
| if (callback) { |
| callback(sensor->GetSensorData()); |
| } |
| } |
| std::chrono::steady_clock::time_point last_refresh_end_time = |
| sensor->GetLastRefreshEndTime(); |
| if (last_refresh_end_time != std::chrono::steady_clock::time_point::min()) { |
| sensor->UpdateSoftwarePollingEndMetrics(std::chrono::steady_clock::now() - |
| last_refresh_end_time); |
| } |
| sensor->SetLastRefreshEndTime(std::chrono::steady_clock::now()); |
| }); |
| } |
| |
| } // namespace milotic_tlbmc |