blob: 3d57dc75f3260207532b1d06116fefbe8ea4133d [file] [log] [blame]
#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_