ESPHome  2023.3.1
sun.h
Go to the documentation of this file.
1 #pragma once
2 
4 #include "esphome/core/helpers.h"
7 
8 namespace esphome {
9 namespace sun {
10 
11 namespace internal {
12 
13 /* Usually, ESPHome uses single-precision floating point values
14  * because those tend to be accurate enough and are more efficient.
15  *
16  * However, some of the data in this class has to be quite accurate, so double is
17  * used everywhere.
18  */
19 using num_t = double;
20 struct GeoLocation {
23 
24  num_t latitude_rad() const;
25  num_t longitude_rad() const;
26 };
27 
28 struct Moment {
30 
31  num_t jd() const;
32  num_t jde() const;
33 };
34 
38 
39  num_t right_ascension_rad() const;
40  num_t declination_rad() const;
41 };
42 
46 
47  num_t elevation_rad() const;
48  num_t azimuth_rad() const;
49 };
50 
51 } // namespace internal
52 
53 class Sun {
54  public:
55  void set_time(time::RealTimeClock *time) { time_ = time; }
56  time::RealTimeClock *get_time() const { return time_; }
57  void set_latitude(double latitude) { location_.latitude = latitude; }
58  void set_longitude(double longitude) { location_.longitude = longitude; }
59 
60  optional<time::ESPTime> sunrise(double elevation);
61  optional<time::ESPTime> sunset(double elevation);
62 
63  double elevation();
64  double azimuth();
65 
66  protected:
67  internal::HorizontalCoordinate calc_coords_();
68  optional<time::ESPTime> calc_event_(bool rising, double zenith);
69 
72 };
73 
74 class SunTrigger : public Trigger<>, public PollingComponent, public Parented<Sun> {
75  public:
77 
78  void set_sunrise(bool sunrise) { sunrise_ = sunrise; }
79  void set_elevation(double elevation) { elevation_ = elevation; }
80 
81  void update() override {
82  double current = this->parent_->elevation();
83  if (std::isnan(current))
84  return;
85 
86  bool crossed;
87  if (this->sunrise_) {
88  crossed = this->last_elevation_ <= this->elevation_ && this->elevation_ < current;
89  } else {
90  crossed = this->last_elevation_ >= this->elevation_ && this->elevation_ > current;
91  }
92 
93  if (crossed && !std::isnan(this->last_elevation_)) {
94  this->trigger();
95  }
96  this->last_elevation_ = current;
97  }
98 
99  protected:
100  bool sunrise_;
101  double last_elevation_{NAN};
102  double elevation_;
103 };
104 
105 template<typename... Ts> class SunCondition : public Condition<Ts...>, public Parented<Sun> {
106  public:
107  TEMPLATABLE_VALUE(double, elevation);
108  void set_above(bool above) { above_ = above; }
109 
110  bool check(Ts... x) override {
111  double elevation = this->elevation_.value(x...);
112  double current = this->parent_->elevation();
113  if (this->above_) {
114  return current > elevation;
115  } else {
116  return current < elevation;
117  }
118  }
119 
120  protected:
121  bool above_;
122 };
123 
124 } // namespace sun
125 } // namespace esphome
internal::GeoLocation location_
Definition: sun.h:71
The RealTimeClock class exposes common timekeeping functions via the device&#39;s local real-time clock...
void set_sunrise(bool sunrise)
Definition: sun.h:78
void set_longitude(double longitude)
Definition: sun.h:58
void update() override
Definition: sun.h:81
This class simplifies creating components that periodically check a state.
Definition: component.h:282
time::RealTimeClock * get_time() const
Definition: sun.h:56
void set_time(time::RealTimeClock *time)
Definition: sun.h:55
A more user-friendly version of struct tm from time.h.
Base class for all automation conditions.
Definition: automation.h:74
void set_elevation(double elevation)
Definition: sun.h:79
void set_above(bool above)
Definition: sun.h:108
bool check(Ts... x) override
Definition: sun.h:110
Definition: a4988.cpp:4
time::RealTimeClock * time_
Definition: sun.h:70
time::ESPTime dt
Definition: sun.h:29
Helper class to easily give an object a parent of type T.
Definition: helpers.h:505
void set_latitude(double latitude)
Definition: sun.h:57