mirror of
https://github.com/esphome/esphome.git
synced 2025-04-15 15:20:27 +01:00
185 lines
6.4 KiB
C++
185 lines
6.4 KiB
C++
#pragma once
|
|
|
|
#include "esphome/components/i2c/i2c.h"
|
|
#include "esphome/components/sensor/sensor.h"
|
|
#include "esphome/core/component.h"
|
|
#include "esphome/core/optional.h"
|
|
#include "esphome/core/automation.h"
|
|
|
|
#include "ltr_definitions_501.h"
|
|
|
|
namespace esphome {
|
|
namespace ltr501 {
|
|
|
|
enum DataAvail : uint8_t { NO_DATA, BAD_DATA, DATA_OK };
|
|
|
|
enum LtrType : uint8_t {
|
|
LTR_TYPE_UNKNOWN = 0,
|
|
LTR_TYPE_ALS_ONLY = 1,
|
|
LTR_TYPE_PS_ONLY = 2,
|
|
LTR_TYPE_ALS_AND_PS = 3,
|
|
};
|
|
|
|
class LTRAlsPs501Component : public PollingComponent, public i2c::I2CDevice {
|
|
public:
|
|
//
|
|
// EspHome framework functions
|
|
//
|
|
float get_setup_priority() const override { return setup_priority::DATA; }
|
|
void setup() override;
|
|
void dump_config() override;
|
|
void update() override;
|
|
void loop() override;
|
|
|
|
// Configuration setters : General
|
|
//
|
|
void set_ltr_type(LtrType type) { this->ltr_type_ = type; }
|
|
|
|
// Configuration setters : ALS
|
|
//
|
|
void set_als_auto_mode(bool enable) { this->automatic_mode_enabled_ = enable; }
|
|
void set_als_gain(AlsGain501 gain) { this->gain_ = gain; }
|
|
void set_als_integration_time(IntegrationTime501 time) { this->integration_time_ = time; }
|
|
void set_als_meas_repeat_rate(MeasurementRepeatRate rate) { this->repeat_rate_ = rate; }
|
|
void set_als_glass_attenuation_factor(float factor) { this->glass_attenuation_factor_ = factor; }
|
|
|
|
// Configuration setters : PS
|
|
//
|
|
void set_ps_high_threshold(uint16_t threshold) { this->ps_threshold_high_ = threshold; }
|
|
void set_ps_low_threshold(uint16_t threshold) { this->ps_threshold_low_ = threshold; }
|
|
void set_ps_cooldown_time_s(uint16_t time) { this->ps_cooldown_time_s_ = time; }
|
|
void set_ps_gain(PsGain501 gain) { this->ps_gain_ = gain; }
|
|
|
|
// Sensors setters
|
|
//
|
|
void set_ambient_light_sensor(sensor::Sensor *sensor) { this->ambient_light_sensor_ = sensor; }
|
|
void set_full_spectrum_counts_sensor(sensor::Sensor *sensor) { this->full_spectrum_counts_sensor_ = sensor; }
|
|
void set_infrared_counts_sensor(sensor::Sensor *sensor) { this->infrared_counts_sensor_ = sensor; }
|
|
void set_actual_gain_sensor(sensor::Sensor *sensor) { this->actual_gain_sensor_ = sensor; }
|
|
void set_actual_integration_time_sensor(sensor::Sensor *sensor) { this->actual_integration_time_sensor_ = sensor; }
|
|
void set_proximity_counts_sensor(sensor::Sensor *sensor) { this->proximity_counts_sensor_ = sensor; }
|
|
|
|
protected:
|
|
//
|
|
// Internal state machine, used to split all the actions into
|
|
// small steps in loop() to make sure we are not blocking execution
|
|
//
|
|
enum class State : uint8_t {
|
|
NOT_INITIALIZED,
|
|
DELAYED_SETUP,
|
|
IDLE,
|
|
WAITING_FOR_DATA,
|
|
COLLECTING_DATA_AUTO,
|
|
DATA_COLLECTED,
|
|
ADJUSTMENT_IN_PROGRESS,
|
|
READY_TO_PUBLISH,
|
|
KEEP_PUBLISHING
|
|
} state_{State::NOT_INITIALIZED};
|
|
|
|
LtrType ltr_type_{LtrType::LTR_TYPE_ALS_ONLY};
|
|
|
|
//
|
|
// Current measurements data
|
|
//
|
|
struct AlsReadings {
|
|
uint16_t ch0{0};
|
|
uint16_t ch1{0};
|
|
AlsGain501 gain{AlsGain501::GAIN_1};
|
|
IntegrationTime501 integration_time{IntegrationTime501::INTEGRATION_TIME_100MS};
|
|
float lux{0.0f};
|
|
uint8_t number_of_adjustments{0};
|
|
} als_readings_;
|
|
uint16_t ps_readings_{0xfffe};
|
|
|
|
inline bool is_als_() const {
|
|
return this->ltr_type_ == LtrType::LTR_TYPE_ALS_ONLY || this->ltr_type_ == LtrType::LTR_TYPE_ALS_AND_PS;
|
|
}
|
|
inline bool is_ps_() const {
|
|
return this->ltr_type_ == LtrType::LTR_TYPE_PS_ONLY || this->ltr_type_ == LtrType::LTR_TYPE_ALS_AND_PS;
|
|
}
|
|
|
|
//
|
|
// Device interaction and data manipulation
|
|
//
|
|
bool check_part_number_();
|
|
|
|
void configure_reset_();
|
|
void configure_als_();
|
|
void configure_integration_time_(IntegrationTime501 time);
|
|
void configure_gain_(AlsGain501 gain);
|
|
DataAvail is_als_data_ready_(AlsReadings &data);
|
|
void read_sensor_data_(AlsReadings &data);
|
|
bool are_adjustments_required_(AlsReadings &data);
|
|
void apply_lux_calculation_(AlsReadings &data);
|
|
void publish_data_part_1_(AlsReadings &data);
|
|
void publish_data_part_2_(AlsReadings &data);
|
|
|
|
void configure_ps_();
|
|
uint16_t read_ps_data_();
|
|
void check_and_trigger_ps_();
|
|
|
|
//
|
|
// Component configuration
|
|
//
|
|
bool automatic_mode_enabled_{false};
|
|
AlsGain501 gain_{AlsGain501::GAIN_1};
|
|
IntegrationTime501 integration_time_{IntegrationTime501::INTEGRATION_TIME_100MS};
|
|
MeasurementRepeatRate repeat_rate_{MeasurementRepeatRate::REPEAT_RATE_500MS};
|
|
float glass_attenuation_factor_{1.0};
|
|
|
|
uint16_t ps_cooldown_time_s_{5};
|
|
PsGain501 ps_gain_{PsGain501::PS_GAIN_1};
|
|
uint16_t ps_threshold_high_{0xffff};
|
|
uint16_t ps_threshold_low_{0x0000};
|
|
|
|
//
|
|
// Sensors for publishing data
|
|
//
|
|
sensor::Sensor *infrared_counts_sensor_{nullptr}; // direct reading CH1, infrared only
|
|
sensor::Sensor *full_spectrum_counts_sensor_{nullptr}; // direct reading CH0, infrared + visible light
|
|
sensor::Sensor *ambient_light_sensor_{nullptr}; // calculated lux
|
|
sensor::Sensor *actual_gain_sensor_{nullptr}; // actual gain of reading
|
|
sensor::Sensor *actual_integration_time_sensor_{nullptr}; // actual integration time
|
|
sensor::Sensor *proximity_counts_sensor_{nullptr}; // proximity sensor
|
|
|
|
bool is_any_als_sensor_enabled_() const {
|
|
return this->ambient_light_sensor_ != nullptr || this->full_spectrum_counts_sensor_ != nullptr ||
|
|
this->infrared_counts_sensor_ != nullptr || this->actual_gain_sensor_ != nullptr ||
|
|
this->actual_integration_time_sensor_ != nullptr;
|
|
}
|
|
bool is_any_ps_sensor_enabled_() const { return this->proximity_counts_sensor_ != nullptr; }
|
|
|
|
//
|
|
// Trigger section for the automations
|
|
//
|
|
friend class LTRPsHighTrigger;
|
|
friend class LTRPsLowTrigger;
|
|
|
|
CallbackManager<void()> on_ps_high_trigger_callback_;
|
|
CallbackManager<void()> on_ps_low_trigger_callback_;
|
|
|
|
void add_on_ps_high_trigger_callback_(std::function<void()> callback) {
|
|
this->on_ps_high_trigger_callback_.add(std::move(callback));
|
|
}
|
|
|
|
void add_on_ps_low_trigger_callback_(std::function<void()> callback) {
|
|
this->on_ps_low_trigger_callback_.add(std::move(callback));
|
|
}
|
|
};
|
|
|
|
class LTRPsHighTrigger : public Trigger<> {
|
|
public:
|
|
explicit LTRPsHighTrigger(LTRAlsPs501Component *parent) {
|
|
parent->add_on_ps_high_trigger_callback_([this]() { this->trigger(); });
|
|
}
|
|
};
|
|
|
|
class LTRPsLowTrigger : public Trigger<> {
|
|
public:
|
|
explicit LTRPsLowTrigger(LTRAlsPs501Component *parent) {
|
|
parent->add_on_ps_low_trigger_callback_([this]() { this->trigger(); });
|
|
}
|
|
};
|
|
} // namespace ltr501
|
|
} // namespace esphome
|