diff --git a/esphome/components/ccs811/ccs811.cpp b/esphome/components/ccs811/ccs811.cpp index 538d7fe1f5..e7928d4d8b 100644 --- a/esphome/components/ccs811/ccs811.cpp +++ b/esphome/components/ccs811/ccs811.cpp @@ -102,10 +102,14 @@ void CCS811Component::send_env_data_() { // temperature has a 25° offset to allow negative temperatures temperature += 25; - // only 0.5 fractions are supported (application note) - auto hum_value = static_cast(roundf(humidity * 2)); - auto temp_value = static_cast(roundf(temperature * 2)); - this->write_bytes(0x05, {hum_value, 0x00, temp_value, 0x00}); + // At page 18 of: + // https://cdn.sparkfun.com/datasheets/BreakoutBoards/CCS811_Programming_Guide.pdf + // Reference code: + // https://github.com/adafruit/Adafruit_CCS811/blob/0990f5c620354d8bc087c4706bec091d8e6e5dfd/Adafruit_CCS811.cpp#L135-L142 + uint16_t hum_conv = static_cast(lroundf(humidity * 512.0f + 0.5f)); + uint16_t temp_conv = static_cast(lroundf(temperature * 512.0f + 0.5f)); + this->write_bytes(0x05, {(uint8_t)((hum_conv >> 8) & 0xff), (uint8_t)((hum_conv & 0xff)), + (uint8_t)((temp_conv >> 8) & 0xff), (uint8_t)((temp_conv & 0xff))}); } void CCS811Component::dump_config() { ESP_LOGCONFIG(TAG, "CCS811"); diff --git a/esphome/components/ds1307/ds1307.cpp b/esphome/components/ds1307/ds1307.cpp index 599ec16e4f..2f33768132 100644 --- a/esphome/components/ds1307/ds1307.cpp +++ b/esphome/components/ds1307/ds1307.cpp @@ -16,7 +16,7 @@ void DS1307Component::setup() { } } -void DS1307Component::update() { this->read(); } +void DS1307Component::update() { this->read_time(); } void DS1307Component::dump_config() { ESP_LOGCONFIG(TAG, "DS1307:"); @@ -29,7 +29,7 @@ void DS1307Component::dump_config() { float DS1307Component::get_setup_priority() const { return setup_priority::DATA; } -void DS1307Component::read() { +void DS1307Component::read_time() { if (!this->read_rtc_()) { return; } @@ -53,7 +53,7 @@ void DS1307Component::read() { time::RealTimeClock::synchronize_epoch_(rtc_time.timestamp); } -void DS1307Component::write() { +void DS1307Component::write_time() { auto now = time::RealTimeClock::utcnow(); if (!now.is_valid()) { ESP_LOGE(TAG, "Invalid system time, not syncing to RTC."); diff --git a/esphome/components/ds1307/ds1307.h b/esphome/components/ds1307/ds1307.h index 8e318bf395..2e9ac2275c 100644 --- a/esphome/components/ds1307/ds1307.h +++ b/esphome/components/ds1307/ds1307.h @@ -13,8 +13,8 @@ class DS1307Component : public time::RealTimeClock, public i2c::I2CDevice { void update() override; void dump_config() override; float get_setup_priority() const override; - void read(); - void write(); + void read_time(); + void write_time(); protected: bool read_rtc_(); @@ -59,12 +59,12 @@ class DS1307Component : public time::RealTimeClock, public i2c::I2CDevice { template class WriteAction : public Action, public Parented { public: - void play(Ts... x) override { this->parent_->write(); } + void play(Ts... x) override { this->parent_->write_time(); } }; template class ReadAction : public Action, public Parented { public: - void play(Ts... x) override { this->parent_->read(); } + void play(Ts... x) override { this->parent_->read_time(); } }; } // namespace ds1307 } // namespace esphome diff --git a/esphome/components/ds1307/time.py b/esphome/components/ds1307/time.py index c381fb7b2a..371dc85be8 100644 --- a/esphome/components/ds1307/time.py +++ b/esphome/components/ds1307/time.py @@ -18,19 +18,19 @@ CONFIG_SCHEMA = time.TIME_SCHEMA.extend({ }).extend(i2c.i2c_device_schema(0x68)) -@automation.register_action('ds1307.write', WriteAction, cv.Schema({ +@automation.register_action('ds1307.write_time', WriteAction, cv.Schema({ cv.GenerateID(): cv.use_id(DS1307Component), })) -def ds1307_write_to_code(config, action_id, template_arg, args): +def ds1307_write_time_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({ +@automation.register_action('ds1307.read_time', ReadAction, automation.maybe_simple_id({ cv.GenerateID(): cv.use_id(DS1307Component), })) -def ds1307_read_to_code(config, action_id, template_arg, args): +def ds1307_read_time_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 diff --git a/esphome/components/light/addressable_light.h b/esphome/components/light/addressable_light.h index a95d70f274..4e7ec4b931 100644 --- a/esphome/components/light/addressable_light.h +++ b/esphome/components/light/addressable_light.h @@ -149,10 +149,10 @@ struct ESPColor { return ESPColor(uint8_t((uint16_t(r) * 255U / max_rgb)), uint8_t((uint16_t(g) * 255U / max_rgb)), uint8_t((uint16_t(b) * 255U / max_rgb)), w); } - ESPColor fade_to_white(uint8_t amnt) { return ESPColor(255, 255, 255, 255) - (*this * amnt); } - ESPColor fade_to_black(uint8_t amnt) { return *this * amnt; } - ESPColor lighten(uint8_t delta) { return *this + delta; } - ESPColor darken(uint8_t delta) { return *this - delta; } + ESPColor fade_to_white(uint8_t amnt) const { return ESPColor(255, 255, 255, 255) - (*this * amnt); } + ESPColor fade_to_black(uint8_t amnt) const { return *this * amnt; } + ESPColor lighten(uint8_t delta) const { return *this + delta; } + ESPColor darken(uint8_t delta) const { return *this - delta; } static const ESPColor BLACK; static const ESPColor WHITE; diff --git a/esphome/components/sntp/sntp_component.cpp b/esphome/components/sntp/sntp_component.cpp index 641d66091c..4050609dd8 100644 --- a/esphome/components/sntp/sntp_component.cpp +++ b/esphome/components/sntp/sntp_component.cpp @@ -54,6 +54,7 @@ void SNTPComponent::loop() { char buf[128]; time.strftime(buf, sizeof(buf), "%c"); ESP_LOGD(TAG, "Synchronized time: %s", buf); + this->time_sync_callback_.call(); this->has_time_ = true; } diff --git a/esphome/components/st7735/st7735.cpp b/esphome/components/st7735/st7735.cpp index e433a08334..2a3d8fc903 100644 --- a/esphome/components/st7735/st7735.cpp +++ b/esphome/components/st7735/st7735.cpp @@ -454,6 +454,7 @@ void HOT ST7735::write_display_data_() { } else { this->write_array(this->buffer_, this->get_buffer_length()); } + this->disable(); } void ST7735::spi_master_write_addr_(uint16_t addr1, uint16_t addr2) { diff --git a/esphome/components/time/__init__.py b/esphome/components/time/__init__.py index e5ed5034ab..5f30a8f2ee 100644 --- a/esphome/components/time/__init__.py +++ b/esphome/components/time/__init__.py @@ -11,8 +11,8 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.const import CONF_ID, CONF_CRON, CONF_DAYS_OF_MONTH, CONF_DAYS_OF_WEEK, CONF_HOURS, \ - CONF_MINUTES, CONF_MONTHS, CONF_ON_TIME, CONF_SECONDS, CONF_TIMEZONE, CONF_TRIGGER_ID, \ - CONF_AT, CONF_SECOND, CONF_HOUR, CONF_MINUTE + CONF_MINUTES, CONF_MONTHS, CONF_ON_TIME, CONF_ON_TIME_SYNC, CONF_SECONDS, CONF_TIMEZONE, \ + CONF_TRIGGER_ID, CONF_AT, CONF_SECOND, CONF_HOUR, CONF_MINUTE from esphome.core import coroutine, coroutine_with_priority from esphome.automation import Condition @@ -24,6 +24,7 @@ IS_PLATFORM_COMPONENT = True time_ns = cg.esphome_ns.namespace('time') RealTimeClock = time_ns.class_('RealTimeClock', cg.PollingComponent) CronTrigger = time_ns.class_('CronTrigger', automation.Trigger.template(), cg.Component) +SyncTrigger = time_ns.class_('SyncTrigger', automation.Trigger.template(), cg.Component) ESPTime = time_ns.struct('ESPTime') TimeHasTimeCondition = time_ns.class_('TimeHasTimeCondition', Condition) @@ -294,6 +295,9 @@ TIME_SCHEMA = cv.Schema({ cv.Optional(CONF_CRON): validate_cron_raw, cv.Optional(CONF_AT): validate_time_at, }, validate_cron_keys), + cv.Optional(CONF_ON_TIME_SYNC): automation.validate_automation({ + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SyncTrigger), + }), }).extend(cv.polling_component_schema('15min')) @@ -320,6 +324,12 @@ def setup_time_core_(time_var, config): yield cg.register_component(trigger, conf) yield automation.build_automation(trigger, [], conf) + for conf in config.get(CONF_ON_TIME_SYNC, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], time_var) + + yield cg.register_component(trigger, conf) + yield automation.build_automation(trigger, [], conf) + @coroutine def register_time(time_var, config): diff --git a/esphome/components/time/automation.cpp b/esphome/components/time/automation.cpp index 1232e6f834..8e41fba0da 100644 --- a/esphome/components/time/automation.cpp +++ b/esphome/components/time/automation.cpp @@ -75,5 +75,9 @@ void CronTrigger::add_days_of_week(const std::vector &days_of_week) { } float CronTrigger::get_setup_priority() const { return setup_priority::HARDWARE; } +SyncTrigger::SyncTrigger(RealTimeClock *rtc) : rtc_(rtc) { + rtc->add_on_time_sync_callback([this]() { this->trigger(); }); +} + } // namespace time } // namespace esphome diff --git a/esphome/components/time/automation.h b/esphome/components/time/automation.h index 978d25fbd4..6167aac4f7 100644 --- a/esphome/components/time/automation.h +++ b/esphome/components/time/automation.h @@ -37,5 +37,12 @@ class CronTrigger : public Trigger<>, public Component { optional last_check_; }; +class SyncTrigger : public Trigger<>, public Component { + public: + explicit SyncTrigger(RealTimeClock *rtc); + + protected: + RealTimeClock *rtc_; +}; } // namespace time } // namespace esphome diff --git a/esphome/components/time/real_time_clock.cpp b/esphome/components/time/real_time_clock.cpp index 7d7c1013dd..44ff505ecc 100644 --- a/esphome/components/time/real_time_clock.cpp +++ b/esphome/components/time/real_time_clock.cpp @@ -38,6 +38,8 @@ void RealTimeClock::synchronize_epoch_(uint32_t epoch) { char buf[128]; time.strftime(buf, sizeof(buf), "%c"); ESP_LOGD(TAG, "Synchronized time: %s", buf); + + this->time_sync_callback_.call(); } size_t ESPTime::strftime(char *buffer, size_t buffer_len, const char *format) { diff --git a/esphome/components/time/real_time_clock.h b/esphome/components/time/real_time_clock.h index 880a4e9d5c..a809401c33 100644 --- a/esphome/components/time/real_time_clock.h +++ b/esphome/components/time/real_time_clock.h @@ -127,11 +127,17 @@ class RealTimeClock : public PollingComponent { void call_setup() override; + void add_on_time_sync_callback(std::function callback) { + this->time_sync_callback_.add(std::move(callback)); + }; + protected: /// Report a unix epoch as current time. void synchronize_epoch_(uint32_t epoch); std::string timezone_{}; + + CallbackManager time_sync_callback_; }; template class TimeHasTimeCondition : public Condition { diff --git a/esphome/const.py b/esphome/const.py index 4a5dd2665e..a96d38eb75 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -2,7 +2,7 @@ MAJOR_VERSION = 1 MINOR_VERSION = 16 -PATCH_VERSION = '0b4' +PATCH_VERSION = '0b5' __short_version__ = f'{MAJOR_VERSION}.{MINOR_VERSION}' __version__ = f'{__short_version__}.{PATCH_VERSION}' @@ -350,6 +350,7 @@ CONF_ON_SHUTDOWN = 'on_shutdown' CONF_ON_STATE = 'on_state' CONF_ON_TAG = 'on_tag' CONF_ON_TIME = 'on_time' +CONF_ON_TIME_SYNC = 'on_time_sync' CONF_ON_TURN_OFF = 'on_turn_off' CONF_ON_TURN_ON = 'on_turn_on' CONF_ON_VALUE = 'on_value' diff --git a/tests/test1.yaml b/tests/test1.yaml index f2ebca05ab..5aed1dac44 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -1854,12 +1854,9 @@ time: then: - lambda: 'ESP_LOGD("main", "time");' - platform: gps - update_interval: 1h - on_time: - seconds: 0 - minutes: /15 + on_time_sync: then: - ds1307.write: + ds1307.write_time: id: ds1307_time - platform: ds1307 id: ds1307_time @@ -1867,7 +1864,7 @@ time: on_time: seconds: 0 then: - ds1307.read + ds1307.read_time cover: - platform: template