From 01bbd04a5a800a375c11a895f73281801f026e5a Mon Sep 17 00:00:00 2001 From: Kevin Pelzel Date: Wed, 23 Sep 2020 21:07:51 -0600 Subject: [PATCH 01/13] Add Fan and Swing Support to fujitsu-general Component (#1287) * Added fan and swing support to fujitsu-general * fixed formatting --- .../fujitsu_general/fujitsu_general.cpp | 60 ++++++++++++++++--- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/esphome/components/fujitsu_general/fujitsu_general.cpp b/esphome/components/fujitsu_general/fujitsu_general.cpp index 261d8be258..f611464248 100644 --- a/esphome/components/fujitsu_general/fujitsu_general.cpp +++ b/esphome/components/fujitsu_general/fujitsu_general.cpp @@ -36,7 +36,10 @@ const uint8_t FUJITSU_GENERAL_FAN_HIGH_BYTE10 = 0x01; const uint8_t FUJITSU_GENERAL_FAN_MEDIUM_BYTE10 = 0x02; const uint8_t FUJITSU_GENERAL_FAN_LOW_BYTE10 = 0x03; const uint8_t FUJITSU_GENERAL_FAN_SILENT_BYTE10 = 0x04; -const uint8_t FUJITSU_GENERAL_SWING_MASK_BYTE10 = 0b00010000; +const uint8_t FUJITSU_GENERAL_SWING_NONE_BYTE10 = 0x00; +const uint8_t FUJITSU_GENERAL_SWING_VERTICAL_BYTE10 = 0x01; +const uint8_t FUJITSU_GENERAL_SWING_HORIZONTAL_BYTE10 = 0x02; +const uint8_t FUJITSU_GENERAL_SWING_BOTH_BYTE10 = 0x03; const uint8_t FUJITSU_GENERAL_BASE_BYTE10 = 0x00; const uint8_t FUJITSU_GENERAL_BASE_BYTE11 = 0x00; @@ -74,7 +77,12 @@ const uint16_t FUJITSU_GENERAL_TRL_SPACE = 8000; const uint32_t FUJITSU_GENERAL_CARRIER_FREQUENCY = 38000; -FujitsuGeneralClimate::FujitsuGeneralClimate() : ClimateIR(FUJITSU_GENERAL_TEMP_MIN, FUJITSU_GENERAL_TEMP_MAX, 1) {} +FujitsuGeneralClimate::FujitsuGeneralClimate() + : ClimateIR( + FUJITSU_GENERAL_TEMP_MIN, FUJITSU_GENERAL_TEMP_MAX, 1.0f, true, true, + {climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM, climate::CLIMATE_FAN_HIGH}, + {climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_VERTICAL, climate::CLIMATE_SWING_HORIZONTAL, + climate::CLIMATE_SWING_BOTH}) {} void FujitsuGeneralClimate::transmit_state() { if (this->mode == climate::CLIMATE_MODE_OFF) { @@ -101,8 +109,8 @@ void FujitsuGeneralClimate::transmit_state() { remote_state[15] = FUJITSU_GENERAL_BASE_BYTE15; // Set temperature - uint8_t safecelsius = std::max((uint8_t) this->target_temperature, FUJITSU_GENERAL_TEMP_MIN); - safecelsius = std::min(safecelsius, FUJITSU_GENERAL_TEMP_MAX); + auto safecelsius = + (uint8_t) roundf(clamp(this->target_temperature, FUJITSU_GENERAL_TEMP_MIN, FUJITSU_GENERAL_TEMP_MAX)); remote_state[8] = (byte) safecelsius - 16; remote_state[8] = remote_state[8] << 4; @@ -119,18 +127,52 @@ void FujitsuGeneralClimate::transmit_state() { case climate::CLIMATE_MODE_HEAT: remote_state[9] = FUJITSU_GENERAL_MODE_HEAT_BYTE9; break; + case climate::CLIMATE_MODE_DRY: + remote_state[9] = FUJITSU_GENERAL_MODE_DRY_BYTE9; + break; + case climate::CLIMATE_MODE_FAN_ONLY: + remote_state[9] = FUJITSU_GENERAL_MODE_FAN_BYTE9; + break; case climate::CLIMATE_MODE_AUTO: default: remote_state[9] = FUJITSU_GENERAL_MODE_AUTO_BYTE9; break; - // TODO: CLIMATE_MODE_FAN_ONLY, CLIMATE_MODE_DRY, CLIMATE_MODE_10C are missing in esphome + // TODO: CLIMATE_MODE_10C are missing in esphome } - // TODO: missing support for fan speed - remote_state[10] = FUJITSU_GENERAL_FAN_AUTO_BYTE10; + // Set fan + switch (this->fan_mode) { + case climate::CLIMATE_FAN_HIGH: + remote_state[10] = FUJITSU_GENERAL_FAN_HIGH_BYTE10; + break; + case climate::CLIMATE_FAN_MEDIUM: + remote_state[10] = FUJITSU_GENERAL_FAN_MEDIUM_BYTE10; + break; + case climate::CLIMATE_FAN_LOW: + remote_state[10] = FUJITSU_GENERAL_FAN_LOW_BYTE10; + break; + case climate::CLIMATE_FAN_AUTO: + default: + remote_state[10] = FUJITSU_GENERAL_FAN_AUTO_BYTE10; + break; + } - // TODO: missing support for swing - // remote_state[10] = (byte) remote_state[10] | FUJITSU_GENERAL_SWING_MASK_BYTE10; + // Set swing + switch (this->swing_mode) { + case climate::CLIMATE_SWING_VERTICAL: + remote_state[10] = (byte) remote_state[10] | (FUJITSU_GENERAL_SWING_VERTICAL_BYTE10 << 4); + break; + case climate::CLIMATE_SWING_HORIZONTAL: + remote_state[10] = (byte) remote_state[10] | (FUJITSU_GENERAL_SWING_HORIZONTAL_BYTE10 << 4); + break; + case climate::CLIMATE_SWING_BOTH: + remote_state[10] = (byte) remote_state[10] | (FUJITSU_GENERAL_SWING_BOTH_BYTE10 << 4); + break; + case climate::CLIMATE_SWING_OFF: + default: + remote_state[10] = (byte) remote_state[10] | (FUJITSU_GENERAL_SWING_NONE_BYTE10 << 4); + break; + } // TODO: missing support for outdoor unit low noise // remote_state[14] = (byte) remote_state[14] | FUJITSU_GENERAL_OUTDOOR_UNIT_LOW_NOISE_BYTE14; From 0e59243b83913fc724d0229514a84b6ea14717cc Mon Sep 17 00:00:00 2001 From: Florian Gareis Date: Sat, 26 Sep 2020 12:02:13 +0200 Subject: [PATCH 02/13] Replace CENTER_LEFT with TOP_LEFT to match other printf function (#1295) --- esphome/components/display/display_buffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/display/display_buffer.cpp b/esphome/components/display/display_buffer.cpp index bd468dcbc3..a329f6f58a 100644 --- a/esphome/components/display/display_buffer.cpp +++ b/esphome/components/display/display_buffer.cpp @@ -299,7 +299,7 @@ void DisplayBuffer::printf(int x, int y, Font *font, TextAlign align, const char void DisplayBuffer::printf(int x, int y, Font *font, const char *format, ...) { va_list arg; va_start(arg, format); - this->vprintf_(x, y, font, COLOR_ON, TextAlign::CENTER_LEFT, format, arg); + this->vprintf_(x, y, font, COLOR_ON, TextAlign::TOP_LEFT, format, arg); va_end(arg); } void DisplayBuffer::set_writer(display_writer_t &&writer) { this->writer_ = writer; } From 0ccfdd47118e9158d2138691fc0dc6766ebd9b60 Mon Sep 17 00:00:00 2001 From: rspaargaren Date: Sun, 27 Sep 2020 19:17:28 +0200 Subject: [PATCH 03/13] Enable reverse display of the Max7219 digit (#1234) * add reverse option * Update max7219digit.cpp adding space for formatting * Update esphome/components/max7219digit/display.py Copy past error... Co-authored-by: Otto Winter Co-authored-by: Otto Winter --- esphome/components/max7219digit/display.py | 3 +++ esphome/components/max7219digit/max7219digit.cpp | 6 +++++- esphome/components/max7219digit/max7219digit.h | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/esphome/components/max7219digit/display.py b/esphome/components/max7219digit/display.py index eb6d112a64..e9aba13287 100644 --- a/esphome/components/max7219digit/display.py +++ b/esphome/components/max7219digit/display.py @@ -11,6 +11,7 @@ CONF_SCROLL_DWELL = 'scroll_dwell' CONF_SCROLL_DELAY = 'scroll_delay' CONF_SCROLL_ENABLE = 'scroll_enable' CONF_SCROLL_MODE = 'scroll_mode' +CONF_REVERSE_ENABLE = 'reverse_enable' SCROLL_MODES = { 'CONTINUOUS': 0, @@ -39,6 +40,7 @@ CONFIG_SCHEMA = display.BASIC_DISPLAY_SCHEMA.extend({ cv.Optional(CONF_SCROLL_SPEED, default='250ms'): cv.positive_time_period_milliseconds, cv.Optional(CONF_SCROLL_DELAY, default='1000ms'): cv.positive_time_period_milliseconds, cv.Optional(CONF_SCROLL_DWELL, default='1000ms'): cv.positive_time_period_milliseconds, + cv.Optional(CONF_REVERSE_ENABLE, default=False): cv.boolean, }).extend(cv.polling_component_schema('500ms')).extend(spi.spi_device_schema(cs_pin_required=True)) @@ -56,6 +58,7 @@ def to_code(config): cg.add(var.set_scroll_delay(config[CONF_SCROLL_DELAY])) cg.add(var.set_scroll(config[CONF_SCROLL_ENABLE])) cg.add(var.set_scroll_mode(config[CONF_SCROLL_MODE])) + cg.add(var.set_reverse(config[CONF_REVERSE_ENABLE])) if CONF_LAMBDA in config: lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], [(MAX7219ComponentRef, 'it')], diff --git a/esphome/components/max7219digit/max7219digit.cpp b/esphome/components/max7219digit/max7219digit.cpp index ab9be4ad36..eb77e63617 100644 --- a/esphome/components/max7219digit/max7219digit.cpp +++ b/esphome/components/max7219digit/max7219digit.cpp @@ -108,7 +108,11 @@ void MAX7219Component::display() { // Send the data to the chip for (uint8_t i = 0; i < this->num_chips_; i++) { for (uint8_t j = 0; j < 8; j++) { - pixels[j] = this->max_displaybuffer_[i * 8 + j]; + if (this->reverse_) { + pixels[j] = this->max_displaybuffer_[(this->num_chips_ - i - 1) * 8 + j]; + } else { + pixels[j] = this->max_displaybuffer_[i * 8 + j]; + } } this->send64pixels(i, pixels); } diff --git a/esphome/components/max7219digit/max7219digit.h b/esphome/components/max7219digit/max7219digit.h index dfd61e84e5..ddefe976a2 100644 --- a/esphome/components/max7219digit/max7219digit.h +++ b/esphome/components/max7219digit/max7219digit.h @@ -52,6 +52,7 @@ class MAX7219Component : public PollingComponent, void set_scroll_delay(uint16_t delay) { this->scroll_delay_ = delay; }; void set_scroll(bool on_off) { this->scroll_ = on_off; }; void set_scroll_mode(uint8_t mode) { this->scroll_mode_ = mode; }; + void set_reverse(bool on_off) { this->reverse_ = on_off; }; void send_char(byte chip, byte data); void send64pixels(byte chip, const byte pixels[8]); @@ -87,6 +88,7 @@ class MAX7219Component : public PollingComponent, uint8_t intensity_; /// Intensity of the display from 0 to 15 (most) uint8_t num_chips_; bool scroll_; + bool reverse_; bool update_{false}; uint16_t scroll_speed_; uint16_t scroll_delay_; From 2ae709c2badefc98515551f395c7b04539991890 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 27 Sep 2020 20:31:21 -0300 Subject: [PATCH 04/13] Bump paho-mqtt from 1.5.0 to 1.5.1 (#1297) Bumps [paho-mqtt](https://github.com/eclipse/paho.mqtt.python) from 1.5.0 to 1.5.1. - [Release notes](https://github.com/eclipse/paho.mqtt.python/releases) - [Changelog](https://github.com/eclipse/paho.mqtt.python/blob/master/ChangeLog.txt) - [Commits](https://github.com/eclipse/paho.mqtt.python/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 29d987fc6c..77e2384816 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ voluptuous==0.11.7 PyYAML==5.3.1 -paho-mqtt==1.5.0 +paho-mqtt==1.5.1 colorlog==4.2.1 tornado==6.0.4 protobuf==3.13.0 From febc485da61aef1c88903433a600324c9a16ee8c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 27 Sep 2020 20:31:46 -0300 Subject: [PATCH 05/13] Bump pytest-cov from 2.10.0 to 2.10.1 (#1253) Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 2.10.0 to 2.10.1. - [Release notes](https://github.com/pytest-dev/pytest-cov/releases) - [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-cov/compare/v2.10.0...v2.10.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements_test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_test.txt b/requirements_test.txt index 6ea351e75b..18f6f52b28 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -6,7 +6,7 @@ pexpect==4.8.0 # Unit tests pytest==6.0.2 -pytest-cov==2.10.0 +pytest-cov==2.10.1 pytest-mock==3.3.1 asyncmock==0.4.2 hypothesis==5.21.0 From e09fefd389c76b55d1366f979e782a1feb360f3a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 30 Sep 2020 06:50:06 +1300 Subject: [PATCH 06/13] Dont fast fail testing so results are not hidden in matrix builds (#1286) --- .github/workflows/ci-docker.yml | 1 + .github/workflows/ci.yml | 2 ++ .github/workflows/release-dev.yml | 2 ++ .github/workflows/release.yml | 2 ++ 4 files changed, 7 insertions(+) diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 8036470f52..b1f2d70381 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -18,6 +18,7 @@ jobs: name: Build docker containers runs-on: ubuntu-latest strategy: + fail-fast: false matrix: arch: [amd64, armv7, aarch64] build_type: ["hassio", "docker"] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6b3c5566b..8136b0678e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,6 +44,7 @@ jobs: container: esphome/esphome-lint:latest # Split clang-tidy check into 4 jobs. Each one will check 1/4th of the .cpp files strategy: + fail-fast: false matrix: split: [1, 2, 3, 4] steps: @@ -107,6 +108,7 @@ jobs: test: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: test: - test1 diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml index 81c3a80b05..a416ccb4ca 100644 --- a/.github/workflows/release-dev.yml +++ b/.github/workflows/release-dev.yml @@ -41,6 +41,7 @@ jobs: container: esphome/esphome-lint:latest # Split clang-tidy check into 4 jobs. Each one will check 1/4th of the .cpp files strategy: + fail-fast: false matrix: split: [1, 2, 3, 4] steps: @@ -104,6 +105,7 @@ jobs: test: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: test: - test1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7ac80355f2..912a618487 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,6 +40,7 @@ jobs: container: esphome/esphome-lint:latest # Split clang-tidy check into 4 jobs. Each one will check 1/4th of the .cpp files strategy: + fail-fast: false matrix: split: [1, 2, 3, 4] steps: @@ -103,6 +104,7 @@ jobs: test: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: test: - test1 From d7b76aadb2fe84137814a0622dfe92a533f5dabd Mon Sep 17 00:00:00 2001 From: buxtronix Date: Fri, 2 Oct 2020 00:24:55 +1000 Subject: [PATCH 07/13] Support Daikin horizontal swing (#1247) Co-authored-by: Ben Buxton --- esphome/components/daikin/daikin.cpp | 39 +++++++++++++++++++++------- esphome/components/daikin/daikin.h | 6 +++-- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/esphome/components/daikin/daikin.cpp b/esphome/components/daikin/daikin.cpp index b6e80d62a7..0701344a8b 100644 --- a/esphome/components/daikin/daikin.cpp +++ b/esphome/components/daikin/daikin.cpp @@ -12,8 +12,10 @@ void DaikinClimate::transmit_state() { 0x00, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00}; remote_state[21] = this->operation_mode_(); - remote_state[24] = this->fan_speed_(); remote_state[22] = this->temperature_(); + uint16_t fan_speed = this->fan_speed_(); + remote_state[24] = fan_speed >> 8; + remote_state[25] = fan_speed & 0xff; // Calculate checksum for (int i = 16; i < 34; i++) { @@ -90,25 +92,38 @@ uint8_t DaikinClimate::operation_mode_() { return operating_mode; } -uint8_t DaikinClimate::fan_speed_() { - uint8_t fan_speed; +uint16_t DaikinClimate::fan_speed_() { + uint16_t fan_speed; switch (this->fan_mode) { case climate::CLIMATE_FAN_LOW: - fan_speed = DAIKIN_FAN_1; + fan_speed = DAIKIN_FAN_1 << 8; break; case climate::CLIMATE_FAN_MEDIUM: - fan_speed = DAIKIN_FAN_3; + fan_speed = DAIKIN_FAN_3 << 8; break; case climate::CLIMATE_FAN_HIGH: - fan_speed = DAIKIN_FAN_5; + fan_speed = DAIKIN_FAN_5 << 8; break; case climate::CLIMATE_FAN_AUTO: default: - fan_speed = DAIKIN_FAN_AUTO; + fan_speed = DAIKIN_FAN_AUTO << 8; } // If swing is enabled switch first 4 bits to 1111 - return this->swing_mode == climate::CLIMATE_SWING_VERTICAL ? fan_speed | 0xF : fan_speed; + switch (this->swing_mode) { + case climate::CLIMATE_SWING_VERTICAL: + fan_speed |= 0x0F00; + break; + case climate::CLIMATE_SWING_HORIZONTAL: + fan_speed |= 0x000F; + break; + case climate::CLIMATE_SWING_BOTH: + fan_speed |= 0x0F0F; + break; + default: + break; + } + return fan_speed; } uint8_t DaikinClimate::temperature_() { @@ -159,13 +174,19 @@ bool DaikinClimate::parse_state_frame_(const uint8_t frame[]) { this->target_temperature = temperature >> 1; } uint8_t fan_mode = frame[8]; - if (fan_mode & 0xF) + uint8_t swing_mode = frame[9]; + if (fan_mode & 0xF && swing_mode & 0xF) + this->swing_mode = climate::CLIMATE_SWING_BOTH; + else if (fan_mode & 0xF) this->swing_mode = climate::CLIMATE_SWING_VERTICAL; + else if (swing_mode & 0xF) + this->swing_mode = climate::CLIMATE_SWING_HORIZONTAL; else this->swing_mode = climate::CLIMATE_SWING_OFF; switch (fan_mode & 0xF0) { case DAIKIN_FAN_1: case DAIKIN_FAN_2: + case DAIKIN_FAN_SILENT: this->fan_mode = climate::CLIMATE_FAN_LOW; break; case DAIKIN_FAN_3: diff --git a/esphome/components/daikin/daikin.h b/esphome/components/daikin/daikin.h index 4671d57570..c0a472bce7 100644 --- a/esphome/components/daikin/daikin.h +++ b/esphome/components/daikin/daikin.h @@ -21,6 +21,7 @@ const uint8_t DAIKIN_MODE_ON = 0x01; // Fan Speed const uint8_t DAIKIN_FAN_AUTO = 0xA0; +const uint8_t DAIKIN_FAN_SILENT = 0xB0; const uint8_t DAIKIN_FAN_1 = 0x30; const uint8_t DAIKIN_FAN_2 = 0x40; const uint8_t DAIKIN_FAN_3 = 0x50; @@ -46,13 +47,14 @@ class DaikinClimate : public climate_ir::ClimateIR { DAIKIN_TEMP_MIN, DAIKIN_TEMP_MAX, 1.0f, true, true, std::vector{climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM, climate::CLIMATE_FAN_HIGH}, - std::vector{climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_VERTICAL}) {} + std::vector{climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_VERTICAL, + climate::CLIMATE_SWING_HORIZONTAL, climate::CLIMATE_SWING_BOTH}) {} protected: // Transmit via IR the state of this climate controller. void transmit_state() override; uint8_t operation_mode_(); - uint8_t fan_speed_(); + uint16_t fan_speed_(); uint8_t temperature_(); // Handle received IR Buffer bool on_receive(remote_base::RemoteReceiveData data) override; From 89cde158d6e659cb60c88d2754393776bebfae26 Mon Sep 17 00:00:00 2001 From: Ivo-tje <56391648+Ivo-tje@users.noreply.github.com> Date: Thu, 1 Oct 2020 20:00:00 +0200 Subject: [PATCH 08/13] Table row wasn't closed (#1310) Co-authored-by: Ivo --- esphome/components/web_server/web_server.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 48a47080b2..9e0e881b1b 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -31,6 +31,7 @@ void write_row(AsyncResponseStream *stream, Nameable *obj, const std::string &kl stream->print(""); stream->print(action.c_str()); stream->print(""); + stream->print(""); } UrlMatch match_url(const std::string &url, bool only_domain = false) { From dbec3d7c505c9465c60ae1769b5b33a7e8513e87 Mon Sep 17 00:00:00 2001 From: James Gao Date: Thu, 1 Oct 2020 15:47:29 -0700 Subject: [PATCH 09/13] Typo in the pm2.5 grid (#1311) The incorrect pm2.5 grid results in incorrect AQI values in the 51-100 range. --- esphome/components/hm3301/aqi_calculator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/hm3301/aqi_calculator.cpp b/esphome/components/hm3301/aqi_calculator.cpp index 6b70c5d4fd..ac573fbad6 100644 --- a/esphome/components/hm3301/aqi_calculator.cpp +++ b/esphome/components/hm3301/aqi_calculator.cpp @@ -17,7 +17,7 @@ class AQICalculator : public AbstractAQICalculator { int index_grid_[AMOUNT_OF_LEVELS][2] = {{0, 51}, {51, 100}, {101, 150}, {151, 200}, {201, 300}, {301, 500}}; - int pm2_5_calculation_grid_[AMOUNT_OF_LEVELS][2] = {{0, 12}, {13, 45}, {36, 55}, {56, 150}, {151, 250}, {251, 500}}; + int pm2_5_calculation_grid_[AMOUNT_OF_LEVELS][2] = {{0, 12}, {13, 35}, {36, 55}, {56, 150}, {151, 250}, {251, 500}}; int pm10_0_calculation_grid_[AMOUNT_OF_LEVELS][2] = {{0, 54}, {55, 154}, {155, 254}, {255, 354}, {355, 424}, {425, 604}}; From 002861f13b2e3a9dfd16a1157b12894daf08a6cb Mon Sep 17 00:00:00 2001 From: dubit0 Date: Fri, 2 Oct 2020 00:55:42 +0200 Subject: [PATCH 10/13] Float output: Fix min_power and max_power adjusting when output is inverted (#1250) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes faulty behaviour when both, invert and min_power/max_power are set for a float output (e.g. PWM). The current code scales the output level to the range [min_power, max_power] and subsequently inverts the value. This leads to values that are outside the range [min_power, max_power]. This patch fixes the problem by inverting the requested level first and then scaling it to the interval [min_power, max_power]. Co-authored-by: Thomas Niederprüm --- esphome/components/output/float_output.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/esphome/components/output/float_output.cpp b/esphome/components/output/float_output.cpp index 0d536d0946..d9f2db559c 100644 --- a/esphome/components/output/float_output.cpp +++ b/esphome/components/output/float_output.cpp @@ -29,10 +29,9 @@ void FloatOutput::set_level(float state) { this->power_.unrequest(); } #endif - - float adjusted_value = (state * (this->max_power_ - this->min_power_)) + this->min_power_; if (this->is_inverted()) - adjusted_value = 1.0f - adjusted_value; + state = 1.0f - state; + float adjusted_value = (state * (this->max_power_ - this->min_power_)) + this->min_power_; this->write_state(adjusted_value); } From 5c86f332b269fd3e4bffcbdf3359a021419effdd Mon Sep 17 00:00:00 2001 From: Ash McKenzie Date: Mon, 5 Oct 2020 02:22:28 +1100 Subject: [PATCH 11/13] Add new time.has_time condition (#1255) --- esphome/components/time/__init__.py | 12 +++++++++++- esphome/components/time/real_time_clock.h | 10 ++++++++++ tests/test3.yaml | 1 + 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/esphome/components/time/__init__.py b/esphome/components/time/__init__.py index ddbc1d6093..5f071aef11 100644 --- a/esphome/components/time/__init__.py +++ b/esphome/components/time/__init__.py @@ -10,10 +10,11 @@ import tzlocal import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation -from esphome.const import CONF_CRON, CONF_DAYS_OF_MONTH, CONF_DAYS_OF_WEEK, CONF_HOURS, \ +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 from esphome.core import coroutine, coroutine_with_priority +from esphome.automation import Condition _LOGGER = logging.getLogger(__name__) @@ -24,6 +25,7 @@ time_ns = cg.esphome_ns.namespace('time') RealTimeClock = time_ns.class_('RealTimeClock', cg.Component) CronTrigger = time_ns.class_('CronTrigger', automation.Trigger.template(), cg.Component) ESPTime = time_ns.struct('ESPTime') +TimeHasTimeCondition = time_ns.class_('TimeHasTimeCondition', Condition) def _tz_timedelta(td): @@ -328,3 +330,11 @@ def register_time(time_var, config): def to_code(config): cg.add_define('USE_TIME') cg.add_global(time_ns.using) + + +@automation.register_condition('time.has_time', TimeHasTimeCondition, cv.Schema({ + cv.GenerateID(): cv.use_id(RealTimeClock), +})) +def time_has_time_to_code(config, condition_id, template_arg, args): + paren = yield cg.get_variable(config[CONF_ID]) + yield cg.new_Pvariable(condition_id, template_arg, paren) diff --git a/esphome/components/time/real_time_clock.h b/esphome/components/time/real_time_clock.h index 9f40fdc5b5..8de4509089 100644 --- a/esphome/components/time/real_time_clock.h +++ b/esphome/components/time/real_time_clock.h @@ -2,6 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/helpers.h" +#include "esphome/core/automation.h" #include #include #include @@ -133,5 +134,14 @@ class RealTimeClock : public Component { std::string timezone_{}; }; +template class TimeHasTimeCondition : public Condition { + public: + TimeHasTimeCondition(RealTimeClock *parent) : parent_(parent) {} + bool check(Ts... x) override { return this->parent_->now().is_valid(); } + + protected: + RealTimeClock *parent_; +}; + } // namespace time } // namespace esphome diff --git a/tests/test3.yaml b/tests/test3.yaml index 14cb4a4e47..550f7baf6f 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -8,6 +8,7 @@ esphome: - wait_until: - api.connected - wifi.connected + - time.has_time includes: - custom.h From e35d56defe09eeaebd57b9c15d138a21dc72d53f Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Mon, 5 Oct 2020 14:15:40 -0700 Subject: [PATCH 12/13] Fix max7219digit chip_rotation: 180 (#1321) Co-authored-by: Samuel Sieb --- esphome/components/max7219digit/max7219digit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/max7219digit/max7219digit.cpp b/esphome/components/max7219digit/max7219digit.cpp index eb77e63617..b2f9c90f9a 100644 --- a/esphome/components/max7219digit/max7219digit.cpp +++ b/esphome/components/max7219digit/max7219digit.cpp @@ -233,7 +233,7 @@ void MAX7219Component::send64pixels(uint8_t chip, const uint8_t pixels[8]) { b = pixels[col]; } else if (this->orientation_ == 2) { for (uint8_t i = 0; i < 8; i++) { - b |= ((pixels[i] >> (7 - col)) << (7 - i)); + b |= ((pixels[i] >> (7 - col)) & 1) << i; } } else { b = pixels[7 - col]; From 4988349677a4c078f011c76b176b329baa7453ce Mon Sep 17 00:00:00 2001 From: MartinWelsch Date: Sun, 11 Oct 2020 03:50:53 +0200 Subject: [PATCH 13/13] Fix Light Trigger (#1308) * make LightTransitionTransformer publish at end * adjust on trigger + cleanup * add target_state_reached_callback_ * fix format * revert publish_at_end change * fix bug for rapid on/off switching + remove debug logging * formatting * call state reached callback when no transition Co-authored-by: Guillermo Ruffino --- esphome/components/light/automation.h | 21 +++++++-------------- esphome/components/light/light_state.cpp | 8 ++++++++ esphome/components/light/light_state.h | 13 +++++++++++++ 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/esphome/components/light/automation.h b/esphome/components/light/automation.h index b240f84e8f..d1fb2a0bcb 100644 --- a/esphome/components/light/automation.h +++ b/esphome/components/light/automation.h @@ -102,17 +102,18 @@ class LightTurnOnTrigger : public Trigger<> { public: LightTurnOnTrigger(LightState *a_light) { a_light->add_new_remote_values_callback([this, a_light]() { - auto is_on = a_light->current_values.is_on(); + // using the remote value because of transitions we need to trigger as early as possible + auto is_on = a_light->remote_values.is_on(); // only trigger when going from off to on - auto should_trigger = is_on && !last_on_; + auto should_trigger = is_on && !this->last_on_; // Set new state immediately so that trigger() doesn't devolve // into infinite loop - last_on_ = is_on; + this->last_on_ = is_on; if (should_trigger) { this->trigger(); } }); - last_on_ = a_light->current_values.is_on(); + this->last_on_ = a_light->current_values.is_on(); } protected: @@ -122,22 +123,14 @@ class LightTurnOnTrigger : public Trigger<> { class LightTurnOffTrigger : public Trigger<> { public: LightTurnOffTrigger(LightState *a_light) { - a_light->add_new_remote_values_callback([this, a_light]() { + a_light->add_new_target_state_reached_callback([this, a_light]() { auto is_on = a_light->current_values.is_on(); // only trigger when going from on to off - auto should_trigger = !is_on && last_on_; - // Set new state immediately so that trigger() doesn't devolve - // into infinite loop - last_on_ = is_on; - if (should_trigger) { + if (!is_on) { this->trigger(); } }); - last_on_ = a_light->current_values.is_on(); } - - protected: - bool last_on_; }; template class AddressableSet : public Action { diff --git a/esphome/components/light/light_state.cpp b/esphome/components/light/light_state.cpp index d34bc88f53..346ab1876d 100644 --- a/esphome/components/light/light_state.cpp +++ b/esphome/components/light/light_state.cpp @@ -145,6 +145,7 @@ void LightState::loop() { if (this->transformer_ != nullptr) { if (this->transformer_->is_finished()) { this->remote_values = this->current_values = this->transformer_->get_end_values(); + this->target_state_reached_callback_.call(); if (this->transformer_->publish_at_end()) this->publish_state(); this->transformer_ = nullptr; @@ -336,6 +337,9 @@ void LightCall::perform() { this->parent_->set_immediately_(v, this->publish_); } + if (!this->has_transition_()) { + this->parent_->target_state_reached_callback_.call(); + } if (this->publish_) { this->parent_->publish_state(); } @@ -752,6 +756,10 @@ void LightState::current_values_as_cwww(float *cold_white, float *warm_white, bo void LightState::add_new_remote_values_callback(std::function &&send_callback) { this->remote_values_callback_.add(std::move(send_callback)); } +void LightState::add_new_target_state_reached_callback(std::function &&send_callback) { + this->target_state_reached_callback_.add(std::move(send_callback)); +} + LightEffect *LightState::get_active_effect_() { if (this->active_effect_index_ == 0) return nullptr; diff --git a/esphome/components/light/light_state.h b/esphome/components/light/light_state.h index e48cf9f864..e761e576e3 100644 --- a/esphome/components/light/light_state.h +++ b/esphome/components/light/light_state.h @@ -242,6 +242,13 @@ class LightState : public Nameable, public Component { */ void add_new_remote_values_callback(std::function &&send_callback); + /** + * The callback is called once the state of current_values and remote_values are equal + * + * @param send_callback + */ + void add_new_target_state_reached_callback(std::function &&send_callback); + /// Return whether the light has any effects that meet the trait requirements. bool supports_effects(); @@ -318,6 +325,12 @@ class LightState : public Nameable, public Component { * starting with the beginning of the transition. */ CallbackManager remote_values_callback_{}; + + /** Callback to call when the state of current_values and remote_values are equal + * This should be called once the state of current_values changed and equals the state of remote_values + */ + CallbackManager target_state_reached_callback_{}; + LightOutput *output_; ///< Store the output to allow effects to have more access. /// Whether the light value should be written in the next cycle. bool next_write_{true};