component.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #pragma once
  2. #include <string>
  3. #include <functional>
  4. #include "Arduino.h"
  5. #include "esphome/core/optional.h"
  6. namespace esphome {
  7. /** Default setup priorities for components of different types.
  8. *
  9. * Components should return one of these setup priorities in get_setup_priority.
  10. */
  11. namespace setup_priority {
  12. /// For communication buses like i2c/spi
  13. extern const float BUS;
  14. /// For components that represent GPIO pins like PCF8573
  15. extern const float IO;
  16. /// For components that deal with hardware and are very important like GPIO switch
  17. extern const float HARDWARE;
  18. /// For components that import data from directly connected sensors like DHT.
  19. extern const float DATA;
  20. /// Alias for DATA (here for compatability reasons)
  21. extern const float HARDWARE_LATE;
  22. /// For components that use data from sensors like displays
  23. extern const float PROCESSOR;
  24. extern const float WIFI;
  25. /// For components that should be initialized after WiFi is connected.
  26. extern const float AFTER_WIFI;
  27. /// For components that should be initialized after a data connection (API/MQTT) is connected.
  28. extern const float AFTER_CONNECTION;
  29. /// For components that should be initialized at the very end of the setup process.
  30. extern const float LATE;
  31. } // namespace setup_priority
  32. #define LOG_UPDATE_INTERVAL(this) \
  33. if (this->get_update_interval() < 100) { \
  34. ESP_LOGCONFIG(TAG, " Update Interval: %.3fs", this->get_update_interval() / 1000.0f); \
  35. } else { \
  36. ESP_LOGCONFIG(TAG, " Update Interval: %.1fs", this->get_update_interval() / 1000.0f); \
  37. }
  38. extern const uint32_t COMPONENT_STATE_MASK;
  39. extern const uint32_t COMPONENT_STATE_CONSTRUCTION;
  40. extern const uint32_t COMPONENT_STATE_SETUP;
  41. extern const uint32_t COMPONENT_STATE_LOOP;
  42. extern const uint32_t COMPONENT_STATE_FAILED;
  43. extern const uint32_t STATUS_LED_MASK;
  44. extern const uint32_t STATUS_LED_OK;
  45. extern const uint32_t STATUS_LED_WARNING;
  46. extern const uint32_t STATUS_LED_ERROR;
  47. class Component {
  48. public:
  49. /** Where the component's initialization should happen.
  50. *
  51. * Analogous to Arduino's setup(). This method is guaranteed to only be called once.
  52. * Defaults to doing nothing.
  53. */
  54. virtual void setup();
  55. /** This method will be called repeatedly.
  56. *
  57. * Analogous to Arduino's loop(). setup() is guaranteed to be called before this.
  58. * Defaults to doing nothing.
  59. */
  60. virtual void loop();
  61. virtual void dump_config();
  62. /** priority of setup(). higher -> executed earlier
  63. *
  64. * Defaults to 0.
  65. *
  66. * @return The setup priority of this component
  67. */
  68. virtual float get_setup_priority() const;
  69. float get_actual_setup_priority() const;
  70. void set_setup_priority(float priority);
  71. /** priority of loop(). higher -> executed earlier
  72. *
  73. * Defaults to 0.
  74. *
  75. * @return The loop priority of this component
  76. */
  77. virtual float get_loop_priority() const;
  78. void call();
  79. virtual void on_shutdown() {}
  80. virtual void on_safe_shutdown() {}
  81. uint32_t get_component_state() const;
  82. /** Mark this component as failed. Any future timeouts/intervals/setup/loop will no longer be called.
  83. *
  84. * This might be useful if a component wants to indicate that a connection to its peripheral failed.
  85. * For example, i2c based components can check if the remote device is responding and otherwise
  86. * mark the component as failed. Eventually this will also enable smart status LEDs.
  87. */
  88. virtual void mark_failed();
  89. bool is_failed();
  90. virtual bool can_proceed();
  91. bool status_has_warning();
  92. bool status_has_error();
  93. void status_set_warning();
  94. void status_set_error();
  95. void status_clear_warning();
  96. void status_clear_error();
  97. void status_momentary_warning(const std::string &name, uint32_t length = 5000);
  98. void status_momentary_error(const std::string &name, uint32_t length = 5000);
  99. bool has_overridden_loop() const;
  100. protected:
  101. virtual void call_loop();
  102. virtual void call_setup();
  103. /** Set an interval function with a unique name. Empty name means no cancelling possible.
  104. *
  105. * This will call f every interval ms. Can be cancelled via CancelInterval().
  106. * Similar to javascript's setInterval().
  107. *
  108. * IMPORTANT: Do not rely on this having correct timing. This is only called from
  109. * loop() and therefore can be significantly delay. If you need exact timing please
  110. * use hardware timers.
  111. *
  112. * @param name The identifier for this interval function.
  113. * @param interval The interval in ms.
  114. * @param f The function (or lambda) that should be called
  115. *
  116. * @see cancel_interval()
  117. */
  118. void set_interval(const std::string &name, uint32_t interval, std::function<void()> &&f); // NOLINT
  119. void set_interval(uint32_t interval, std::function<void()> &&f); // NOLINT
  120. /** Cancel an interval function.
  121. *
  122. * @param name The identifier for this interval function.
  123. * @return Whether an interval functions was deleted.
  124. */
  125. bool cancel_interval(const std::string &name); // NOLINT
  126. void set_timeout(uint32_t timeout, std::function<void()> &&f); // NOLINT
  127. /** Set a timeout function with a unique name.
  128. *
  129. * Similar to javascript's setTimeout(). Empty name means no cancelling possible.
  130. *
  131. * IMPORTANT: Do not rely on this having correct timing. This is only called from
  132. * loop() and therefore can be significantly delay. If you need exact timing please
  133. * use hardware timers.
  134. *
  135. * @param name The identifier for this timeout function.
  136. * @param timeout The timeout in ms.
  137. * @param f The function (or lambda) that should be called
  138. *
  139. * @see cancel_timeout()
  140. */
  141. void set_timeout(const std::string &name, uint32_t timeout, std::function<void()> &&f); // NOLINT
  142. /** Cancel a timeout function.
  143. *
  144. * @param name The identifier for this timeout function.
  145. * @return Whether a timeout functions was deleted.
  146. */
  147. bool cancel_timeout(const std::string &name); // NOLINT
  148. /** Defer a callback to the next loop() call.
  149. *
  150. * If name is specified and a defer() object with the same name exists, the old one is first removed.
  151. *
  152. * @param name The name of the defer function.
  153. * @param f The callback.
  154. */
  155. void defer(const std::string &name, std::function<void()> &&f); // NOLINT
  156. /// Defer a callback to the next loop() call.
  157. void defer(std::function<void()> &&f); // NOLINT
  158. /// Cancel a defer callback using the specified name, name must not be empty.
  159. bool cancel_defer(const std::string &name); // NOLINT
  160. uint32_t component_state_{0x0000}; ///< State of this component.
  161. float setup_priority_override_{NAN};
  162. };
  163. /** This class simplifies creating components that periodically check a state.
  164. *
  165. * You basically just need to implement the update() function, it will be called every update_interval ms
  166. * after startup. Note that this class cannot guarantee a correct timing, as it's not using timers, just
  167. * a software polling feature with set_interval() from Component.
  168. */
  169. class PollingComponent : public Component {
  170. public:
  171. PollingComponent() : PollingComponent(0) {}
  172. /** Initialize this polling component with the given update interval in ms.
  173. *
  174. * @param update_interval The update interval in ms.
  175. */
  176. explicit PollingComponent(uint32_t update_interval);
  177. /** Manually set the update interval in ms for this polling object.
  178. *
  179. * Override this if you want to do some validation for the update interval.
  180. *
  181. * @param update_interval The update interval in ms.
  182. */
  183. virtual void set_update_interval(uint32_t update_interval);
  184. // ========== OVERRIDE METHODS ==========
  185. // (You'll only need this when creating your own custom sensor)
  186. virtual void update() = 0;
  187. // ========== INTERNAL METHODS ==========
  188. // (In most use cases you won't need these)
  189. void call_setup() override;
  190. /// Get the update interval in ms of this sensor
  191. virtual uint32_t get_update_interval() const;
  192. protected:
  193. uint32_t update_interval_;
  194. };
  195. /// Helper class that enables naming of objects so that it doesn't have to be re-implement every time.
  196. class Nameable {
  197. public:
  198. Nameable() : Nameable("") {}
  199. explicit Nameable(const std::string &name);
  200. const std::string &get_name() const;
  201. void set_name(const std::string &name);
  202. /// Get the sanitized name of this nameable as an ID. Caching it internally.
  203. const std::string &get_object_id();
  204. uint32_t get_object_id_hash();
  205. bool is_internal() const;
  206. void set_internal(bool internal);
  207. protected:
  208. virtual uint32_t hash_base() = 0;
  209. void calc_object_id_();
  210. std::string name_;
  211. std::string object_id_;
  212. uint32_t object_id_hash_;
  213. bool internal_{false};
  214. };
  215. } // namespace esphome