Skip to content
This repository has been archived by the owner on Sep 27, 2023. It is now read-only.

[Huge] New Actions/Conditions, Custom Platforms, MQTT Stability #274

Merged
merged 12 commits into from Dec 5, 2018
4 changes: 2 additions & 2 deletions examples/pcf8574/pcf8574.cpp
Expand Up @@ -13,8 +13,8 @@ void setup() {
App.init_i2c(SDA, SCL, true);

auto *pcf8574 = App.make_pcf8574_component(0x21);
App.make_gpio_binary_sensor("PCF pin 0 sensor", pcf8574->make_input_pin(0, PCF8574_INPUT));
App.make_gpio_binary_sensor("PCF pin 1 sensor", pcf8574->make_input_pin(1, PCF8574_INPUT_PULLUP));
App.make_gpio_binary_sensor("PCF pin 0 sensor", pcf8574->make_input_pin(0, INPUT));
App.make_gpio_binary_sensor("PCF pin 1 sensor", pcf8574->make_input_pin(1, INPUT_PULLUP));

App.make_gpio_switch("PCF pin 4 switch", pcf8574->make_output_pin(4));
auto *out = App.make_gpio_output(pcf8574->make_output_pin(5));
Expand Down
38 changes: 32 additions & 6 deletions src/esphomelib/application.cpp
Expand Up @@ -119,10 +119,21 @@ void HOT Application::loop() {
feed_wdt();
}
global_state = new_global_state;
yield();

if (first_loop)
const uint32_t now = millis();
if (HighFrequencyLoopRequester::is_high_frequency()) {
yield();
} else {
uint32_t delay_time = this->loop_interval_;
if (now - this->last_loop_ < this->loop_interval_)
delay_time = this->loop_interval_ - (now - this->last_loop_);
delay(delay_time);
}
this->last_loop_ = now;

if (first_loop) {
ESP_LOGI(TAG, "First loop finished successfully!");
}
}

WiFiComponent *Application::init_wifi(const std::string &ssid, const std::string &password) {
Expand Down Expand Up @@ -796,10 +807,6 @@ Application::MakeRotaryEncoderSensor Application::make_rotary_encoder_sensor(con
}
#endif

mqtt::MQTTMessageTrigger *Application::make_mqtt_message_trigger(const std::string &topic, uint8_t qos) {
return global_mqtt_client->make_message_trigger(topic, qos);
}

StartupTrigger *Application::make_startup_trigger() {
return this->register_component(new StartupTrigger());
}
Expand Down Expand Up @@ -1248,6 +1255,25 @@ Application::MakeTotalDailyEnergySensor Application::make_total_daily_energy_sen
}
#endif

void Application::set_loop_interval(uint32_t loop_interval) {
this->loop_interval_ = loop_interval;
}

void Application::register_component_(Component *comp) {
if (comp == nullptr) {
ESP_LOGW(TAG, "Tried to register null component!");
return;
}

for (auto *c : this->components_) {
if (comp == c) {
ESP_LOGW(TAG, "Component already registered! (%p)", c);
return;
}
}
this->components_.push_back(comp);
}


Application App; // NOLINT

Expand Down
34 changes: 28 additions & 6 deletions src/esphomelib/application.h
Expand Up @@ -6,6 +6,7 @@
#include "esphomelib/automation.h"
#include "esphomelib/component.h"
#include "esphomelib/controller.h"
#include "esphomelib/custom_component.h"
#include "esphomelib/debug_component.h"
#include "esphomelib/deep_sleep_component.h"
#include "esphomelib/esp32_ble_beacon.h"
Expand All @@ -24,6 +25,7 @@
#include "esphomelib/web_server.h"
#include "esphomelib/wifi_component.h"
#include "esphomelib/binary_sensor/binary_sensor.h"
#include "esphomelib/binary_sensor/custom_binary_sensor.h"
#include "esphomelib/binary_sensor/esp32_touch_binary_sensor.h"
#include "esphomelib/binary_sensor/filter.h"
#include "esphomelib/binary_sensor/gpio_binary_sensor_component.h"
Expand Down Expand Up @@ -52,9 +54,11 @@
#include "esphomelib/light/light_output_component.h"
#include "esphomelib/light/light_state.h"
#include "esphomelib/light/mqtt_json_light_component.h"
#include "esphomelib/mqtt/custom_mqtt_device.h"
#include "esphomelib/mqtt/mqtt_client_component.h"
#include "esphomelib/mqtt/mqtt_component.h"
#include "esphomelib/output/binary_output.h"
#include "esphomelib/output/custom_output.h"
#include "esphomelib/output/esp8266_pwm_output.h"
#include "esphomelib/output/float_output.h"
#include "esphomelib/output/gpio_binary_output_component.h"
Expand All @@ -78,6 +82,7 @@
#include "esphomelib/sensor/bmp085_component.h"
#include "esphomelib/sensor/bmp280_component.h"
#include "esphomelib/sensor/cse7766.h"
#include "esphomelib/sensor/custom_sensor.h"
#include "esphomelib/sensor/dallas_component.h"
#include "esphomelib/sensor/dht12_component.h"
#include "esphomelib/sensor/dht_component.h"
Expand Down Expand Up @@ -109,8 +114,9 @@
#include "esphomelib/sensor/ultrasonic_sensor.h"
#include "esphomelib/sensor/uptime_sensor.h"
#include "esphomelib/sensor/wifi_signal_sensor.h"
#include "esphomelib/stepper/stepper.h"
#include "esphomelib/stepper/a4988.h"
#include "esphomelib/stepper/stepper.h"
#include "esphomelib/switch_/custom_switch.h"
#include "esphomelib/switch_/gpio_switch.h"
#include "esphomelib/switch_/mqtt_switch_component.h"
#include "esphomelib/switch_/output_switch.h"
Expand All @@ -119,6 +125,7 @@
#include "esphomelib/switch_/switch.h"
#include "esphomelib/switch_/template_switch.h"
#include "esphomelib/switch_/uart_switch.h"
#include "esphomelib/text_sensor/custom_text_sensor.h"
#include "esphomelib/text_sensor/mqtt_subscribe_text_sensor.h"
#include "esphomelib/text_sensor/mqtt_text_sensor.h"
#include "esphomelib/text_sensor/template_text_sensor.h"
Expand Down Expand Up @@ -326,8 +333,6 @@ class Application {
template<typename T>
Automation<T> *make_automation(Trigger<T> *trigger);

mqtt::MQTTMessageTrigger *make_mqtt_message_trigger(const std::string &topic, uint8_t qos = 0);

StartupTrigger *make_startup_trigger();

ShutdownTrigger *make_shutdown_trigger();
Expand Down Expand Up @@ -1344,7 +1349,24 @@ class Application {

const std::string &get_compilation_time() const;

/** Set the target interval with which to run the loop() calls.
* If the loop() method takes longer than the target interval, esphomelib won't
* sleep in loop(), but if the time spent in loop() is small than the target, esphomelib
* will delay at the end of the App.loop() method.
*
* This is done to conserve power: In most use-cases, high-speed loop() calls are not required
* and degrade power consumption.
*
* Each component can request a high frequency loop execution by using the HighFrequencyLoopRequester
* helper in helpers.h
*
* @param loop_interval The interval in milliseconds to run the core loop at. Defaults to 16 milliseconds.
*/
void set_loop_interval(uint32_t loop_interval);

protected:
void register_component_(Component *comp);

std::vector<Component *> components_{};
std::vector<Controller *> controllers_{};
mqtt::MQTTClientComponent *mqtt_client_{nullptr};
Expand All @@ -1353,6 +1375,8 @@ class Application {
std::string name_;
std::string compilation_time_;
uint32_t application_state_{COMPONENT_STATE_CONSTRUCTION};
uint32_t last_loop_{0};
uint32_t loop_interval_{16};
#ifdef USE_I2C
I2CComponent *i2c_{nullptr};
#endif
Expand All @@ -1364,9 +1388,7 @@ extern Application App;
template<class C>
C *Application::register_component(C *c) {
static_assert(std::is_base_of<Component, C>::value, "Only Component subclasses can be registered");
Component *component = c;
if (c != nullptr)
this->components_.push_back(component);
this->register_component_((Component *) c);
return c;
}

Expand Down
11 changes: 7 additions & 4 deletions src/esphomelib/automation.cpp
Expand Up @@ -2,11 +2,11 @@

ESPHOMELIB_NAMESPACE_BEGIN

void Trigger<NoArg>::add_on_trigger_callback(std::function<void(NoArg)> &&f) {
this->on_trigger_.add(std::move(f));
}
void Trigger<NoArg>::trigger() {
this->on_trigger_.call(false);
this->parent_->process_trigger_(false);
}
void Trigger<NoArg>::set_parent(Automation<NoArg> *parent) {
this->parent_ = parent;
}

void StartupTrigger::setup() {
Expand Down Expand Up @@ -63,6 +63,9 @@ void RangeCondition::set_max(float max) {
void Script::execute() {
this->trigger();
}
void Script::stop() {
this->parent_->stop();
}

ESPHOMELIB_NAMESPACE_END