From 585bb6dac808040d1539d814bb1984e1a14236dd Mon Sep 17 00:00:00 2001 From: Alex <33379584+alexyao2015@users.noreply.github.com> Date: Fri, 8 Jan 2021 13:11:42 -0600 Subject: [PATCH 1/5] fix safe_mode (#1421) * Deprioritize automations Ensures safe mode is loaded before any automations are ran * Fix lint --- esphome/core_config.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/esphome/core_config.py b/esphome/core_config.py index f167eb8d8b..f1bb18eef5 100644 --- a/esphome/core_config.py +++ b/esphome/core_config.py @@ -209,11 +209,8 @@ def _esp8266_add_lwip_type(): cg.add_build_flag('-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH') -@coroutine_with_priority(100.0) -def to_code(config): - cg.add_global(cg.global_ns.namespace('esphome').using) - cg.add(cg.App.pre_setup(config[CONF_NAME], cg.RawExpression('__DATE__ ", " __TIME__'))) - +@coroutine_with_priority(30.0) +def _add_automations(config): for conf in config.get(CONF_ON_BOOT, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], conf.get(CONF_PRIORITY)) yield cg.register_component(trigger, conf) @@ -229,6 +226,14 @@ def to_code(config): yield cg.register_component(trigger, conf) yield automation.build_automation(trigger, [], conf) + +@coroutine_with_priority(100.0) +def to_code(config): + cg.add_global(cg.global_ns.namespace('esphome').using) + cg.add(cg.App.pre_setup(config[CONF_NAME], cg.RawExpression('__DATE__ ", " __TIME__'))) + + CORE.add_job(_add_automations, config) + # Set LWIP build constants for ESP8266 if CORE.is_esp8266: CORE.add_job(_esp8266_add_lwip_type) From dcd3d2084d3645afedcd53fa3e3702329a528965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=B6sch?= Date: Fri, 8 Jan 2021 23:40:22 +0100 Subject: [PATCH 2/5] DS1307 real time clock component (#1441) * initial support for DS1307 real time clock * add simple test, make sync functions public * cleanup lint * add sync to/from rtc actions * changes action names * Update esphome/components/ds1307/ds1307.cpp Co-authored-by: Guillermo Ruffino * Update esphome/components/ds1307/time.py Co-authored-by: Guillermo Ruffino * fix suggested change Co-authored-by: Guillermo Ruffino --- CODEOWNERS | 1 + esphome/components/ds1307/__init__.py | 0 esphome/components/ds1307/ds1307.cpp | 104 ++++++++++++++++++++++++++ esphome/components/ds1307/ds1307.h | 69 +++++++++++++++++ esphome/components/ds1307/time.py | 44 +++++++++++ tests/test1.yaml | 14 ++++ 6 files changed, 232 insertions(+) create mode 100644 esphome/components/ds1307/__init__.py create mode 100644 esphome/components/ds1307/ds1307.cpp create mode 100644 esphome/components/ds1307/ds1307.h create mode 100644 esphome/components/ds1307/time.py diff --git a/CODEOWNERS b/CODEOWNERS index 9cf1d30e19..95729bae8d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -29,6 +29,7 @@ esphome/components/ct_clamp/* @jesserockz esphome/components/debug/* @OttoWinter esphome/components/dfplayer/* @glmnet esphome/components/dht/* @OttoWinter +esphome/components/ds1307/* @badbadc0ffee esphome/components/exposure_notifications/* @OttoWinter esphome/components/ezo/* @ssieb esphome/components/fastled_base/* @OttoWinter diff --git a/esphome/components/ds1307/__init__.py b/esphome/components/ds1307/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/ds1307/ds1307.cpp b/esphome/components/ds1307/ds1307.cpp new file mode 100644 index 0000000000..990767ddd4 --- /dev/null +++ b/esphome/components/ds1307/ds1307.cpp @@ -0,0 +1,104 @@ +#include "ds1307.h" +#include "esphome/core/log.h" + +// Datasheet: +// - https://datasheets.maximintegrated.com/en/ds/DS1307.pdf + +namespace esphome { +namespace ds1307 { + +static const char *TAG = "ds1307"; + +void DS1307Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up DS1307..."); + if (!this->read_rtc_()) { + this->mark_failed(); + } + this->set_interval(15 * 60 * 1000, [&]() { this->read(); }); +} + +void DS1307Component::dump_config() { + ESP_LOGCONFIG(TAG, "DS1307:"); + LOG_I2C_DEVICE(this); + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with DS1307 failed!"); + } + ESP_LOGCONFIG(TAG, " Timezone: '%s'", this->timezone_.c_str()); +} + +float DS1307Component::get_setup_priority() const { return setup_priority::DATA; } + +void DS1307Component::read() { + if (!this->read_rtc_()) { + return; + } + if (ds1307_.reg.ch) { + ESP_LOGW(TAG, "RTC halted, not syncing to system clock."); + return; + } + time::ESPTime rtc_time{.second = uint8_t(ds1307_.reg.second + 10 * ds1307_.reg.second_10), + .minute = uint8_t(ds1307_.reg.minute + 10u * ds1307_.reg.minute_10), + .hour = uint8_t(ds1307_.reg.hour + 10u * ds1307_.reg.hour_10), + .day_of_week = uint8_t(ds1307_.reg.weekday), + .day_of_month = uint8_t(ds1307_.reg.day + 10u * ds1307_.reg.day_10), + .day_of_year = 1, // ignored by recalc_timestamp_utc(false) + .month = uint8_t(ds1307_.reg.month + 10u * ds1307_.reg.month_10), + .year = uint16_t(ds1307_.reg.year + 10u * ds1307_.reg.year_10 + 2000)}; + rtc_time.recalc_timestamp_utc(false); + if (!rtc_time.is_valid()) { + ESP_LOGE(TAG, "Invalid RTC time, not syncing to system clock."); + return; + } + time::RealTimeClock::synchronize_epoch_(rtc_time.timestamp); +} + +void DS1307Component::write() { + auto now = time::RealTimeClock::utcnow(); + if (!now.is_valid()) { + ESP_LOGE(TAG, "Invalid system time, not syncing to RTC."); + return; + } + ds1307_.reg.year = (now.year - 2000) % 10; + ds1307_.reg.year_10 = (now.year - 2000) / 10 % 10; + ds1307_.reg.month = now.month % 10; + ds1307_.reg.month_10 = now.month / 10; + ds1307_.reg.day = now.day_of_month % 10; + ds1307_.reg.day_10 = now.day_of_month / 10; + ds1307_.reg.weekday = now.day_of_week; + ds1307_.reg.hour = now.hour % 10; + ds1307_.reg.hour_10 = now.hour / 10; + ds1307_.reg.minute = now.minute % 10; + ds1307_.reg.minute_10 = now.minute / 10; + ds1307_.reg.second = now.second % 10; + ds1307_.reg.second_10 = now.second / 10; + ds1307_.reg.ch = false; + + this->write_rtc_(); +} + +bool DS1307Component::read_rtc_() { + if (!this->read_bytes(0, this->ds1307_.raw, sizeof(this->ds1307_.raw))) { + ESP_LOGE(TAG, "Can't read I2C data."); + return false; + } + ESP_LOGD(TAG, "Read %0u%0u:%0u%0u:%0u%0u 20%0u%0u-%0u%0u-%0u%0u CH:%s RS:%0u SQWE:%s OUT:%s", ds1307_.reg.hour_10, + ds1307_.reg.hour, ds1307_.reg.minute_10, ds1307_.reg.minute, ds1307_.reg.second_10, ds1307_.reg.second, + ds1307_.reg.year_10, ds1307_.reg.year, ds1307_.reg.month_10, ds1307_.reg.month, ds1307_.reg.day_10, + ds1307_.reg.day, ONOFF(ds1307_.reg.ch), ds1307_.reg.rs, ONOFF(ds1307_.reg.sqwe), ONOFF(ds1307_.reg.out)); + + return true; +} + +bool DS1307Component::write_rtc_() { + if (!this->write_bytes(0, this->ds1307_.raw, sizeof(this->ds1307_.raw))) { + ESP_LOGE(TAG, "Can't write I2C data."); + return false; + } + ESP_LOGD(TAG, "Write %0u%0u:%0u%0u:%0u%0u 20%0u%0u-%0u%0u-%0u%0u CH:%s RS:%0u SQWE:%s OUT:%s", ds1307_.reg.hour_10, + ds1307_.reg.hour, ds1307_.reg.minute_10, ds1307_.reg.minute, ds1307_.reg.second_10, ds1307_.reg.second, + ds1307_.reg.year_10, ds1307_.reg.year, ds1307_.reg.month_10, ds1307_.reg.month, ds1307_.reg.day_10, + ds1307_.reg.day, ONOFF(ds1307_.reg.ch), ds1307_.reg.rs, ONOFF(ds1307_.reg.sqwe), ONOFF(ds1307_.reg.out)); + return true; +} +} // namespace ds1307 +} // namespace esphome diff --git a/esphome/components/ds1307/ds1307.h b/esphome/components/ds1307/ds1307.h new file mode 100644 index 0000000000..1f732a7c7d --- /dev/null +++ b/esphome/components/ds1307/ds1307.h @@ -0,0 +1,69 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/i2c/i2c.h" +#include "esphome/components/time/real_time_clock.h" + +namespace esphome { +namespace ds1307 { + +class DS1307Component : public time::RealTimeClock, public i2c::I2CDevice { + public: + void setup() override; + void dump_config() override; + float get_setup_priority() const override; + void read(); + void write(); + + protected: + bool read_rtc_(); + bool write_rtc_(); + union DS1307Reg { + struct { + uint8_t second : 4; + uint8_t second_10 : 3; + bool ch : 1; + + uint8_t minute : 4; + uint8_t minute_10 : 3; + uint8_t unused_1 : 1; + + uint8_t hour : 4; + uint8_t hour_10 : 2; + uint8_t unused_2 : 2; + + uint8_t weekday : 3; + uint8_t unused_3 : 5; + + uint8_t day : 4; + uint8_t day_10 : 2; + uint8_t unused_4 : 2; + + uint8_t month : 4; + uint8_t month_10 : 1; + uint8_t unused_5 : 3; + + uint8_t year : 4; + uint8_t year_10 : 4; + + uint8_t rs : 2; + uint8_t unused_6 : 2; + bool sqwe : 1; + uint8_t unused_7 : 2; + bool out : 1; + } reg; + mutable uint8_t raw[sizeof(reg)]; + } ds1307_; +}; + +template class WriteAction : public Action, public Parented { + public: + void play(Ts... x) override { this->parent_->write(); } +}; + +template class ReadAction : public Action, public Parented { + public: + void play(Ts... x) override { this->parent_->read(); } +}; +} // namespace ds1307 +} // namespace esphome diff --git a/esphome/components/ds1307/time.py b/esphome/components/ds1307/time.py new file mode 100644 index 0000000000..c381fb7b2a --- /dev/null +++ b/esphome/components/ds1307/time.py @@ -0,0 +1,44 @@ +import esphome.config_validation as cv +import esphome.codegen as cg +from esphome import automation +from esphome.components import i2c, time +from esphome.const import CONF_ID + + +CODEOWNERS = ['@badbadc0ffee'] +DEPENDENCIES = ['i2c'] +ds1307_ns = cg.esphome_ns.namespace('ds1307') +DS1307Component = ds1307_ns.class_('DS1307Component', time.RealTimeClock, i2c.I2CDevice) +WriteAction = ds1307_ns.class_('WriteAction', automation.Action) +ReadAction = ds1307_ns.class_('ReadAction', automation.Action) + + +CONFIG_SCHEMA = time.TIME_SCHEMA.extend({ + cv.GenerateID(): cv.declare_id(DS1307Component), +}).extend(i2c.i2c_device_schema(0x68)) + + +@automation.register_action('ds1307.write', WriteAction, cv.Schema({ + cv.GenerateID(): cv.use_id(DS1307Component), +})) +def ds1307_write_to_code(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + yield cg.register_parented(var, config[CONF_ID]) + yield var + + +@automation.register_action('ds1307.read', ReadAction, automation.maybe_simple_id({ + cv.GenerateID(): cv.use_id(DS1307Component), +})) +def ds1307_read_to_code(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + yield cg.register_parented(var, config[CONF_ID]) + yield var + + +def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + + yield cg.register_component(var, config) + yield i2c.register_i2c_device(var, config) + yield time.register_time(var, config) diff --git a/tests/test1.yaml b/tests/test1.yaml index 0bccc3f57a..58fc7d4bb2 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -1837,6 +1837,20 @@ time: then: - lambda: 'ESP_LOGD("main", "time");' - platform: gps + on_time: + seconds: 0 + minutes: /15 + then: + ds1307.write: + id: ds1307_time + - platform: ds1307 + id: ds1307_time + on_time: + seconds: 0 + then: + ds1307.read + + cover: - platform: template From c67539cf5b282623b82daa8056a653bb518c622e Mon Sep 17 00:00:00 2001 From: Dan Jackson Date: Sat, 9 Jan 2021 20:53:12 -0800 Subject: [PATCH 3/5] Add encode_uint32 method (#1427) --- esphome/components/api/proto.cpp | 3 +-- esphome/components/max31855/max31855.cpp | 2 +- esphome/components/rdm6300/rdm6300.cpp | 3 +-- esphome/components/tuya/tuya.cpp | 3 +-- esphome/components/xiaomi_ble/xiaomi_ble.cpp | 3 +-- esphome/core/helpers.cpp | 4 ++++ esphome/core/helpers.h | 2 ++ 7 files changed, 11 insertions(+), 9 deletions(-) diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index 3d2f669f54..4bd22af769 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -62,8 +62,7 @@ void ProtoMessage::decode(const uint8_t *buffer, size_t length) { error = true; break; } - uint32_t val = (uint32_t(buffer[i]) << 0) | (uint32_t(buffer[i + 1]) << 8) | (uint32_t(buffer[i + 2]) << 16) | - (uint32_t(buffer[i + 3]) << 24); + uint32_t val = encode_uint32(buffer[i + 3], buffer[i + 2], buffer[i + 1], buffer[i]); if (!this->decode_32bit(field_id, Proto32Bit(val))) { ESP_LOGV(TAG, "Cannot decode 32-bit field %u with value %u!", field_id, val); } diff --git a/esphome/components/max31855/max31855.cpp b/esphome/components/max31855/max31855.cpp index 7a0dc2427c..868cd4f16a 100644 --- a/esphome/components/max31855/max31855.cpp +++ b/esphome/components/max31855/max31855.cpp @@ -41,7 +41,7 @@ void MAX31855Sensor::read_data_() { this->read_array(data, 4); this->disable(); - const uint32_t mem = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3] << 0; + const uint32_t mem = encode_uint32(data[0], data[1], data[2], data[3]); // Verify we got data if (mem != 0xFFFFFFFF) { diff --git a/esphome/components/rdm6300/rdm6300.cpp b/esphome/components/rdm6300/rdm6300.cpp index 6c6f0c0311..2d2ba61824 100644 --- a/esphome/components/rdm6300/rdm6300.cpp +++ b/esphome/components/rdm6300/rdm6300.cpp @@ -46,8 +46,7 @@ void rdm6300::RDM6300Component::loop() { } else { // Valid data this->status_clear_warning(); - const uint32_t result = (uint32_t(this->buffer_[1]) << 24) | (uint32_t(this->buffer_[2]) << 16) | - (uint32_t(this->buffer_[3]) << 8) | this->buffer_[4]; + const uint32_t result = encode_uint32(this->buffer_[1], this->buffer_[2], this->buffer_[3], this->buffer_[4]); bool report = result != last_id_; for (auto *card : this->cards_) { if (card->process(result)) { diff --git a/esphome/components/tuya/tuya.cpp b/esphome/components/tuya/tuya.cpp index feaab9b0ed..2fd4b27937 100644 --- a/esphome/components/tuya/tuya.cpp +++ b/esphome/components/tuya/tuya.cpp @@ -281,8 +281,7 @@ void Tuya::handle_datapoint_(const uint8_t *buffer, size_t len) { case TuyaDatapointType::INTEGER: if (data_len != 4) return; - datapoint.value_uint = - (uint32_t(data[0]) << 24) | (uint32_t(data[1]) << 16) | (uint32_t(data[2]) << 8) | (uint32_t(data[3]) << 0); + datapoint.value_uint = encode_uint32(data[0], data[1], data[2], data[3]); break; case TuyaDatapointType::ENUM: if (data_len != 1) diff --git a/esphome/components/xiaomi_ble/xiaomi_ble.cpp b/esphome/components/xiaomi_ble/xiaomi_ble.cpp index 202620c06d..75af1e4b7c 100644 --- a/esphome/components/xiaomi_ble/xiaomi_ble.cpp +++ b/esphome/components/xiaomi_ble/xiaomi_ble.cpp @@ -70,8 +70,7 @@ bool parse_xiaomi_value(uint8_t value_type, const uint8_t *data, uint8_t value_l } // idle time since last motion, 4 byte, 32-bit unsigned integer, 1 min else if ((value_type == 0x17) && (value_length == 4)) { - const uint32_t idle_time = - uint32_t(data[0]) | (uint32_t(data[1]) << 8) | (uint32_t(data[2]) << 16) | (uint32_t(data[2]) << 24); + const uint32_t idle_time = encode_uint32(data[3], data[2], data[1], data[0]); result.idle_time = idle_time / 60.0f; result.has_motion = (idle_time) ? false : true; } else { diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 38b80d85fb..f0e0c65f66 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -299,6 +299,10 @@ std::array decode_uint16(uint16_t value) { return {msb, lsb}; } +uint32_t encode_uint32(uint8_t msb, uint8_t byte2, uint8_t byte3, uint8_t lsb) { + return (uint32_t(msb) << 24) | (uint32_t(byte2) << 16) | (uint32_t(byte3) << 8) | uint32_t(lsb); +} + std::string hexencode(const uint8_t *data, uint32_t len) { char buf[20]; std::string res; diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 0c660bdc8e..40e53e601e 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -132,6 +132,8 @@ uint32_t reverse_bits_32(uint32_t x); uint16_t encode_uint16(uint8_t msb, uint8_t lsb); /// Decode a 16-bit unsigned integer into an array of two values: most significant byte, least significant byte. std::array decode_uint16(uint16_t value); +/// Encode a 32-bit unsigned integer given four bytes in MSB -> LSB order +uint32_t encode_uint32(uint8_t msb, uint8_t byte2, uint8_t byte3, uint8_t lsb); /*** * An interrupt helper class. From 72002ce70ecd3018d834abe6c9ed088dc295693b Mon Sep 17 00:00:00 2001 From: mknjc Date: Sun, 10 Jan 2021 20:05:53 +0100 Subject: [PATCH 4/5] Rotary Encoder: Don't call callbacks in the isr (#1456) --- .../rotary_encoder/rotary_encoder.cpp | 51 ++++++++++++++++++- .../rotary_encoder/rotary_encoder.h | 13 +++-- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/esphome/components/rotary_encoder/rotary_encoder.cpp b/esphome/components/rotary_encoder/rotary_encoder.cpp index 873aaf1971..0398489dca 100644 --- a/esphome/components/rotary_encoder/rotary_encoder.cpp +++ b/esphome/components/rotary_encoder/rotary_encoder.cpp @@ -90,16 +90,34 @@ void ICACHE_RAM_ATTR HOT RotaryEncoderSensorStore::gpio_intr(RotaryEncoderSensor if (arg->pin_b->digital_read()) input_state |= STATE_PIN_B_HIGH; + int8_t rotation_dir = 0; uint16_t new_state = STATE_LOOKUP_TABLE[input_state]; if ((new_state & arg->resolution & STATE_HAS_INCREMENTED) != 0) { if (arg->counter < arg->max_value) arg->counter++; - arg->on_clockwise_callback_.call(); + rotation_dir = 1; } if ((new_state & arg->resolution & STATE_HAS_DECREMENTED) != 0) { if (arg->counter > arg->min_value) arg->counter--; - arg->on_anticlockwise_callback_.call(); + rotation_dir = -1; + } + + if (rotation_dir != 0) { + auto first_zero = std::find(arg->rotation_events.begin(), arg->rotation_events.end(), 0); // find first zero + if (first_zero == arg->rotation_events.begin() // are we at the start (first event this loop iteration) + || std::signbit(*std::prev(first_zero)) != + std::signbit(rotation_dir) // or is the last stored event the wrong direction + || *std::prev(first_zero) == std::numeric_limits::lowest() // or the last event slot is full (negative) + || *std::prev(first_zero) == std::numeric_limits::max()) { // or the last event slot is full (positive) + if (first_zero != arg->rotation_events.end()) { // we have a free rotation slot + *first_zero += rotation_dir; // store the rotation into a new slot + } else { + arg->rotation_events_overflow = true; + } + } else { + *std::prev(first_zero) += rotation_dir; // store the rotation into the previous slot + } } arg->state = new_state; @@ -137,6 +155,35 @@ void RotaryEncoderSensor::dump_config() { } } void RotaryEncoderSensor::loop() { + std::array rotation_events; + bool rotation_events_overflow; + ets_intr_lock(); + rotation_events = this->store_.rotation_events; + rotation_events_overflow = this->store_.rotation_events_overflow; + + this->store_.rotation_events.fill(0); + this->store_.rotation_events_overflow = false; + ets_intr_unlock(); + + if (rotation_events_overflow) { + ESP_LOGW(TAG, "Captured more rotation events than expected"); + } + + for (auto events : rotation_events) { + if (events == 0) // we are at the end of the recorded events + break; + + if (events > 0) { + while (events--) { + this->on_clockwise_callback_.call(); + } + } else { + while (events++) { + this->on_anticlockwise_callback_.call(); + } + } + } + if (this->pin_i_ != nullptr && this->pin_i_->digital_read()) { this->store_.counter = 0; } diff --git a/esphome/components/rotary_encoder/rotary_encoder.h b/esphome/components/rotary_encoder/rotary_encoder.h index e066188f22..000350d66c 100644 --- a/esphome/components/rotary_encoder/rotary_encoder.h +++ b/esphome/components/rotary_encoder/rotary_encoder.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "esphome/core/component.h" #include "esphome/core/esphal.h" #include "esphome/core/automation.h" @@ -27,8 +29,8 @@ struct RotaryEncoderSensorStore { int32_t last_read{0}; uint8_t state{0}; - CallbackManager on_clockwise_callback_; - CallbackManager on_anticlockwise_callback_; + std::array rotation_events{}; + bool rotation_events_overflow{false}; static void gpio_intr(RotaryEncoderSensorStore *arg); }; @@ -66,11 +68,11 @@ class RotaryEncoderSensor : public sensor::Sensor, public Component { float get_setup_priority() const override; void add_on_clockwise_callback(std::function callback) { - this->store_.on_clockwise_callback_.add(std::move(callback)); + this->on_clockwise_callback_.add(std::move(callback)); } void add_on_anticlockwise_callback(std::function callback) { - this->store_.on_anticlockwise_callback_.add(std::move(callback)); + this->on_anticlockwise_callback_.add(std::move(callback)); } protected: @@ -79,6 +81,9 @@ class RotaryEncoderSensor : public sensor::Sensor, public Component { GPIOPin *pin_i_{nullptr}; /// Index pin, if this is not nullptr, the counter will reset to 0 once this pin is HIGH. RotaryEncoderSensorStore store_{}; + + CallbackManager on_clockwise_callback_; + CallbackManager on_anticlockwise_callback_; }; template class RotaryEncoderSetValueAction : public Action { From 6a0d4cb5a9e0ad03f42886d0562728ca76c5484c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 11 Jan 2021 20:10:36 +1300 Subject: [PATCH 5/5] Bump version to v1.16.0b2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 9763da791e..659531ee7b 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -2,7 +2,7 @@ MAJOR_VERSION = 1 MINOR_VERSION = 16 -PATCH_VERSION = '0b1' +PATCH_VERSION = '0b2' __short_version__ = f'{MAJOR_VERSION}.{MINOR_VERSION}' __version__ = f'{__short_version__}.{PATCH_VERSION}'