| #ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_SENSORS_SENSOR_H_ |
| #define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_SENSORS_SENSOR_H_ |
| |
| #include <cstddef> |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "absl/base/thread_annotations.h" |
| #include "absl/container/btree_set.h" |
| #include "absl/functional/any_invocable.h" |
| #include "absl/functional/function_ref.h" |
| #include "absl/log/log.h" |
| #include "absl/status/status.h" |
| #include "absl/strings/string_view.h" |
| #include "absl/synchronization/mutex.h" |
| #include "absl/time/time.h" |
| #include "boost/circular_buffer.hpp" //NOLINT: boost is commonly used in BMC |
| #include "entity_common_config.pb.h" |
| #include "i2c_common_config.pb.h" |
| #include "tlbmc/configs/subscription_config.h" |
| #include "resource.pb.h" |
| #include "sensor.pb.h" |
| |
| namespace milotic_tlbmc { |
| |
| std::string GetTrimmedSensorName(absl::string_view sensor_name); |
| |
| // Any implementation of this interface must be thread-safe regarding the listed |
| // functions. |
| class Sensor { |
| public: |
| // Callback used export batch of sensor data. |
| using NotificationCb = absl::FunctionRef<void( |
| std::vector<std::shared_ptr<const SensorValue>> &&)>; |
| |
| static SensorAttributesStatic CreateStaticAttributes( |
| absl::string_view sensor_name, const SensorUnit &sensor_unit, |
| const I2cCommonConfig &i2c_common_config, |
| const EntityCommonConfig &entity_common_config, |
| const ThresholdConfigs &threshold_configs, |
| const ReadingRangeConfigs &reading_range_configs); |
| |
| virtual ~Sensor() = default; |
| |
| // Returns the latest sensor reading. |
| std::shared_ptr<const SensorValue> GetSensorData() const |
| ABSL_LOCKS_EXCLUDED(sensor_data_mutex_) { |
| absl::MutexLock lock(&sensor_data_mutex_); |
| return sensor_data_.empty() ? nullptr : sensor_data_.back(); |
| } |
| |
| std::vector<std::shared_ptr<const SensorValue>> GetSensorDataHistory() const |
| ABSL_LOCKS_EXCLUDED(sensor_data_mutex_) { |
| absl::MutexLock lock(&sensor_data_mutex_); |
| return {sensor_data_.begin(), sensor_data_.end()}; |
| } |
| |
| std::vector<std::shared_ptr<const SensorValue>> GetSensorDataHistorySince( |
| absl::Time start_time) const ABSL_LOCKS_EXCLUDED(sensor_data_mutex_); |
| |
| // Refreshes the sensor data once asynchronously. The sensor data will be |
| // updated when the refresh is done. On errors, nullptr will be fed to the |
| // callback. Detailed error message can be found in the sensor's state. |
| // The `callback` will be called when the refresh is done with the SensorData |
| // that has been refreshed or nullptr if there is an error. The `callback` can |
| // be nullptr. The callback is supposed to be blocking. |
| virtual void RefreshOnceAsync( |
| absl::AnyInvocable<void(const std::shared_ptr<const SensorValue> &)> |
| callback) = 0; |
| |
| // Returns the key of the sensor. A key shall be constant for a sensor's |
| // lifetime. |
| std::string GetKey() const { |
| return sensor_attributes_static_.attributes().key(); |
| } |
| |
| // Returns the config name of the board that contains this sensor. |
| std::string GetConfigName() const { |
| return sensor_attributes_static_.entity_common_config().board_config_name(); |
| } |
| |
| SensorAttributesDynamic GetSensorAttributesDynamic() const { |
| absl::MutexLock lock(&sensor_attributes_dynamic_mutex_); |
| return sensor_attributes_dynamic_; |
| } |
| |
| const SensorAttributesStatic &GetSensorAttributesStatic() const { |
| return sensor_attributes_static_; |
| } |
| |
| // Subscribes to the sensor data. |
| absl::Status Subscribe(const SubscriptionParams *subscription_params); |
| // Deletes an existing subscription. |
| absl::Status Unsubscribe(const SubscriptionParams *subscription_params); |
| void UpdateState(State &&state); |
| // Resize the buffer for the sensor. |
| void ResizeBuffer(size_t buffer_size); |
| |
| protected: |
| Sensor(SensorAttributesStatic &&sensor_attributes_static, |
| std::optional<NotificationCb> notification_cb) |
| : sensor_attributes_static_(std::move(sensor_attributes_static)), |
| sensor_data_(static_cast<size_t>( |
| sensor_attributes_static_.entity_common_config().queue_size())), |
| notification_cb_(notification_cb) {} |
| Sensor() : sensor_data_(1) { |
| DLOG(INFO) << "Sensor created with default queue size of " |
| << sensor_data_.capacity(); |
| } |
| |
| // Buffers the sensor data and notifies the subscribers if the batch size |
| // reaches the threshold. |
| void StoreSensorData(const std::shared_ptr<const SensorValue> &sensor_data) |
| ABSL_LOCKS_EXCLUDED(sensor_data_mutex_, sensor_attributes_dynamic_mutex_); |
| |
| const SensorAttributesStatic sensor_attributes_static_; |
| |
| mutable absl::Mutex sensor_attributes_dynamic_mutex_; |
| SensorAttributesDynamic sensor_attributes_dynamic_ |
| ABSL_GUARDED_BY(sensor_attributes_dynamic_mutex_); |
| |
| mutable absl::Mutex sensor_data_mutex_; |
| // Front() returns the oldest data. |
| boost::circular_buffer<std::shared_ptr<const SensorValue>> sensor_data_ |
| ABSL_GUARDED_BY(sensor_data_mutex_); |
| |
| // The set of batch sizes that are subscribed to the sensor. |
| absl::btree_set<const SubscriptionParams *, SubscriptionParams::Compare> |
| subscription_params_ ABSL_GUARDED_BY(sensor_attributes_dynamic_mutex_); |
| // Callback to be invoked when the batch size reaches the threshold. |
| // Not locked: The callback is instantiated in the constructor and is |
| // supposed to be invoked from a single io_context thread. |
| const std::optional<NotificationCb> notification_cb_ = std::nullopt; |
| }; |
| |
| } // namespace milotic_tlbmc |
| |
| #endif // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_SENSORS_SENSOR_H_ |