From 27f431a02714ee0ca3fe34894a258aa8bc06a818 Mon Sep 17 00:00:00 2001 From: gitolicious Date: Wed, 1 May 2019 20:37:55 +0200 Subject: [PATCH 01/17] Create .gitpod.yml (#508) * Create .gitpod.yml Configure gitpod to install esphome and run dashboard on startup * Replaced file with folder location Co-Authored-By: gitolicious * Use new setup script Co-authored-by: Otto Winter --- .gitpod.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .gitpod.yml diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000000..1859ef44e4 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,6 @@ +ports: +- port: 6052 + onOpen: open-preview +tasks: +- before: script/setup + command: python -m esphome config dashboard From 58586ea8403ed5d4a48d9a38a494903487d3e539 Mon Sep 17 00:00:00 2001 From: Nico Weichbrodt Date: Fri, 3 May 2019 23:46:59 +0200 Subject: [PATCH 02/17] Fix compilation of automations --- esphome/core/automation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/core/automation.h b/esphome/core/automation.h index 7f79ab3ccd..ceed28e5b8 100644 --- a/esphome/core/automation.h +++ b/esphome/core/automation.h @@ -55,7 +55,7 @@ template class Trigger { bool is_running() { if (this->automation_parent_ == nullptr) return false; - return this->automation_parent_.is_running(); + return this->automation_parent_->is_running(); } protected: From c569d022ec282ebb204307707c018deb417e3576 Mon Sep 17 00:00:00 2001 From: mtl010957 Date: Tue, 7 May 2019 15:19:30 -0400 Subject: [PATCH 03/17] Fix MQTT Not Working in dev branch (#527) * Fix MQTT not working * Fix minor typo causing compile error --- esphome/components/mqtt/__init__.py | 5 +++-- esphome/core/automation.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 16a88f39e3..c363f93d06 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -150,12 +150,13 @@ def exp_mqtt_message(config): @coroutine_with_priority(40.0) def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + yield cg.register_component(var, config) + cg.add_library('AsyncMqttClient', '0.8.2') cg.add_define('USE_MQTT') cg.add_global(mqtt_ns.using) - var = cg.new_Pvariable(config[CONF_ID]) - cg.add(var.set_broker_address(config[CONF_BROKER])) cg.add(var.set_broker_port(config[CONF_PORT])) cg.add(var.set_username(config[CONF_USERNAME])) diff --git a/esphome/core/automation.h b/esphome/core/automation.h index 7f79ab3ccd..ceed28e5b8 100644 --- a/esphome/core/automation.h +++ b/esphome/core/automation.h @@ -55,7 +55,7 @@ template class Trigger { bool is_running() { if (this->automation_parent_ == nullptr) return false; - return this->automation_parent_.is_running(); + return this->automation_parent_->is_running(); } protected: From ebb5fadba1c463d4723fd103ce7c8b958b7f9d7c Mon Sep 17 00:00:00 2001 From: Anders Persson Date: Tue, 7 May 2019 21:39:13 +0200 Subject: [PATCH 04/17] Fix custom_sensor codegen (#526) --- esphome/components/custom/sensor/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/custom/sensor/__init__.py b/esphome/components/custom/sensor/__init__.py index 6503cc0c69..284c24e4f0 100644 --- a/esphome/components/custom/sensor/__init__.py +++ b/esphome/components/custom/sensor/__init__.py @@ -20,6 +20,6 @@ def to_code(config): rhs = CustomSensorConstructor(template_) var = cg.variable(config[CONF_ID], rhs) for i, conf in enumerate(config[CONF_SENSORS]): - sens = cg.new_Pvariable(conf[CONF_ID], var.get_switch(i)) + sens = cg.new_Pvariable(conf[CONF_ID], var.get_sensor(i)) cg.add(sens.set_name(conf[CONF_NAME])) yield sensor.register_sensor(sens, conf) From 64541e0e351b2e117938e2cf81ff8adf45388e09 Mon Sep 17 00:00:00 2001 From: Anders Persson Date: Tue, 7 May 2019 23:30:19 +0200 Subject: [PATCH 05/17] Further fix of custom_sensor codegen --- esphome/components/custom/sensor/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/custom/sensor/__init__.py b/esphome/components/custom/sensor/__init__.py index 284c24e4f0..24dcdac997 100644 --- a/esphome/components/custom/sensor/__init__.py +++ b/esphome/components/custom/sensor/__init__.py @@ -20,6 +20,6 @@ def to_code(config): rhs = CustomSensorConstructor(template_) var = cg.variable(config[CONF_ID], rhs) for i, conf in enumerate(config[CONF_SENSORS]): - sens = cg.new_Pvariable(conf[CONF_ID], var.get_sensor(i)) + sens = cg.Pvariable(conf[CONF_ID], var.get_sensor(i)) cg.add(sens.set_name(conf[CONF_NAME])) yield sensor.register_sensor(sens, conf) From 521c080989d43ff83e102184df6c9662b7e8ab4b Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Wed, 8 May 2019 09:58:03 +0200 Subject: [PATCH 06/17] Updates --- esphome/components/adc/adc_sensor.cpp | 14 ++-- esphome/components/adc/adc_sensor.h | 11 ++- esphome/components/adc/sensor.py | 9 ++- esphome/components/ads1115/__init__.py | 2 +- esphome/components/ads1115/ads1115.cpp | 28 ++++--- esphome/components/ads1115/ads1115.h | 15 ++-- esphome/components/ads1115/sensor.py | 12 +-- esphome/components/api/api_server.cpp | 1 - esphome/components/ble_ibeacon/__init__.py | 18 +++++ .../components/ble_presence/binary_sensor.py | 16 ++-- .../ble_presence/ble_presence_device.h | 7 +- esphome/components/ble_rssi/ble_rssi_sensor.h | 7 +- esphome/components/ble_rssi/sensor.py | 16 ++-- .../components/esp32_ble_tracker/__init__.py | 10 ++- .../esp32_ble_tracker/esp32_ble_tracker.cpp | 50 ++++++++---- .../esp32_ble_tracker/esp32_ble_tracker.h | 42 ++++++++-- esphome/components/light/automation.h | 2 +- esphome/components/light/automation.py | 45 ++++++++++- esphome/components/light/types.py | 1 + esphome/components/logger/__init__.py | 8 +- esphome/components/mpu6050/mpu6050.cpp | 7 +- esphome/components/sensor/__init__.py | 2 - esphome/components/time/real_time_clock.cpp | 12 +-- esphome/components/time/real_time_clock.h | 34 +++++++- .../components/voltage_sampler/__init__.py | 4 + .../voltage_sampler/voltage_sampler.h | 16 ++++ esphome/components/wifi/wifi_component.cpp | 4 - esphome/components/wifi/wifi_component.h | 2 - .../components/wifi/wifi_component_esp32.cpp | 2 + .../wifi/wifi_component_esp8266.cpp | 2 + esphome/components/xiaomi_ble/__init__.py | 12 ++- esphome/components/xiaomi_ble/xiaomi_ble.cpp | 2 - esphome/components/xiaomi_ble/xiaomi_ble.h | 4 +- esphome/components/xiaomi_miflora/sensor.py | 15 ++-- .../xiaomi_miflora/xiaomi_miflora.h | 5 +- esphome/components/xiaomi_mijia/sensor.py | 15 ++-- .../components/xiaomi_mijia/xiaomi_mijia.h | 5 +- esphome/const.py | 2 + esphome/core/helpers.h | 1 + script/build_compile_commands.py | 79 +++++++++++++++++++ script/clang-tidy.py | 5 +- 41 files changed, 396 insertions(+), 148 deletions(-) create mode 100644 esphome/components/ble_ibeacon/__init__.py create mode 100644 esphome/components/voltage_sampler/__init__.py create mode 100644 esphome/components/voltage_sampler/voltage_sampler.h create mode 100755 script/build_compile_commands.py diff --git a/esphome/components/adc/adc_sensor.cpp b/esphome/components/adc/adc_sensor.cpp index 849a1f31e5..aef952f27b 100644 --- a/esphome/components/adc/adc_sensor.cpp +++ b/esphome/components/adc/adc_sensor.cpp @@ -48,6 +48,11 @@ void ADCSensor::dump_config() { } float ADCSensor::get_setup_priority() const { return setup_priority::DATA; } void ADCSensor::update() { + float value_v = this->sample(); + ESP_LOGD(TAG, "'%s': Got voltage=%.2fV", this->get_name().c_str(), value_v); + this->publish_state(value_v); +} +float ADCSensor::sample() { #ifdef ARDUINO_ARCH_ESP32 float value_v = analogRead(this->pin_) / 4095.0f; switch (this->attenuation_) { @@ -64,19 +69,16 @@ void ADCSensor::update() { value_v *= 3.9; break; } + return value_v; #endif #ifdef ARDUINO_ARCH_ESP8266 #ifdef USE_ADC_SENSOR_VCC - float value_v = ESP.getVcc() / 1024.0f; + return ESP.getVcc() / 1024.0f; #else - float value_v = analogRead(this->pin_) / 1024.0f; + return analogRead(this->pin_) / 1024.0f; #endif #endif - - ESP_LOGD(TAG, "'%s': Got voltage=%.2fV", this->get_name().c_str(), value_v); - - this->publish_state(value_v); } #ifdef ARDUINO_ARCH_ESP8266 std::string ADCSensor::unique_id() { return get_mac_address() + "-adc"; } diff --git a/esphome/components/adc/adc_sensor.h b/esphome/components/adc/adc_sensor.h index 72afe5c1e9..e44d3ee8d7 100644 --- a/esphome/components/adc/adc_sensor.h +++ b/esphome/components/adc/adc_sensor.h @@ -3,19 +3,23 @@ #include "esphome/core/component.h" #include "esphome/core/esphal.h" #include "esphome/components/sensor/sensor.h" +#include "esphome/components/voltage_sampler/voltage_sampler.h" namespace esphome { namespace adc { -class ADCSensor : public sensor::Sensor, public PollingComponent { +#ifdef USE_ADC_SENSOR_VCC +ADC_MODE(ADC_VCC) +#endif + +class ADCSensor : public sensor::Sensor, public PollingComponent, + public voltage_sampler::VoltageSampler { public: #ifdef ARDUINO_ARCH_ESP32 /// Set the attenuation for this pin. Only available on the ESP32. void set_attenuation(adc_attenuation_t attenuation); #endif - // ========== INTERNAL METHODS ========== - // (In most use cases you won't need these) /// Update adc values. void update() override; /// Setup ADc @@ -24,6 +28,7 @@ class ADCSensor : public sensor::Sensor, public PollingComponent { /// `HARDWARE_LATE` setup priority. float get_setup_priority() const override; void set_pin(uint8_t pin) { this->pin_ = pin; } + float sample() override; #ifdef ARDUINO_ARCH_ESP8266 std::string unique_id() override; diff --git a/esphome/components/adc/sensor.py b/esphome/components/adc/sensor.py index c369ea5be5..6a274f04af 100644 --- a/esphome/components/adc/sensor.py +++ b/esphome/components/adc/sensor.py @@ -1,9 +1,12 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins -from esphome.components import sensor +from esphome.components import sensor, voltage_sampler from esphome.const import CONF_ATTENUATION, CONF_ID, CONF_PIN, ICON_FLASH, UNIT_VOLT + +AUTO_LOAD = ['voltage_sampler'] + ATTENUATION_MODES = { '0db': cg.global_ns.ADC_0db, '2.5db': cg.global_ns.ADC_2_5db, @@ -20,7 +23,8 @@ def validate_adc_pin(value): adc_ns = cg.esphome_ns.namespace('adc') -ADCSensor = adc_ns.class_('ADCSensor', sensor.PollingSensorComponent) +ADCSensor = adc_ns.class_('ADCSensor', sensor.Sensor, cg.PollingComponent, + voltage_sampler.VoltageSampler) CONFIG_SCHEMA = sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 2).extend({ cv.GenerateID(): cv.declare_id(ADCSensor), @@ -37,7 +41,6 @@ def to_code(config): if config[CONF_PIN] == 'VCC': cg.add_define('USE_ADC_SENSOR_VCC') - cg.add_global(cg.global_ns.ADC_MODE(cg.global_ns.ADC_VCC)) else: cg.add(var.set_pin(config[CONF_PIN])) diff --git a/esphome/components/ads1115/__init__.py b/esphome/components/ads1115/__init__.py index e34bab8582..28cfac49ec 100644 --- a/esphome/components/ads1115/__init__.py +++ b/esphome/components/ads1115/__init__.py @@ -4,7 +4,7 @@ from esphome.components import i2c from esphome.const import CONF_ID DEPENDENCIES = ['i2c'] -AUTO_LOAD = ['sensor'] +AUTO_LOAD = ['sensor', 'voltage_sampler'] MULTI_CONF = True ads1115_ns = cg.esphome_ns.namespace('ads1115') diff --git a/esphome/components/ads1115/ads1115.cpp b/esphome/components/ads1115/ads1115.cpp index 398aad3d02..a6fd2d76cd 100644 --- a/esphome/components/ads1115/ads1115.cpp +++ b/esphome/components/ads1115/ads1115.cpp @@ -59,7 +59,9 @@ void ADS1115Component::setup() { } for (auto *sensor : this->sensors_) { this->set_interval(sensor->get_name(), sensor->update_interval(), - [this, sensor] { this->request_measurement_(sensor); }); + [this, sensor] { + this->request_measurement_(sensor); + }); } } void ADS1115Component::dump_config() { @@ -76,11 +78,11 @@ void ADS1115Component::dump_config() { } } float ADS1115Component::get_setup_priority() const { return setup_priority::DATA; } -void ADS1115Component::request_measurement_(ADS1115Sensor *sensor) { +float ADS1115Component::request_measurement_(ADS1115Sensor *sensor) { uint16_t config; if (!this->read_byte_16(ADS1115_REGISTER_CONFIG, &config)) { this->status_set_warning(); - return; + return NAN; } // Multiplexer // 0bxBBBxxxxxxxxxxxx @@ -96,7 +98,7 @@ void ADS1115Component::request_measurement_(ADS1115Sensor *sensor) { if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) { this->status_set_warning(); - return; + return NAN; } // about 1.6 ms with 860 samples per second @@ -107,7 +109,7 @@ void ADS1115Component::request_measurement_(ADS1115Sensor *sensor) { if (millis() - start > 100) { ESP_LOGW(TAG, "Reading ADS1115 timed out"); this->status_set_warning(); - return; + return NAN; } yield(); } @@ -115,7 +117,7 @@ void ADS1115Component::request_measurement_(ADS1115Sensor *sensor) { uint16_t raw_conversion; if (!this->read_byte_16(ADS1115_REGISTER_CONVERSION, &raw_conversion)) { this->status_set_warning(); - return; + return NAN; } auto signed_conversion = static_cast(raw_conversion); @@ -143,16 +145,24 @@ void ADS1115Component::request_measurement_(ADS1115Sensor *sensor) { millivolts = NAN; } - float v = millivolts / 1000.0f; - ESP_LOGD(TAG, "'%s': Got Voltage=%fV", sensor->get_name().c_str(), v); - sensor->publish_state(v); this->status_clear_warning(); + return millivolts / 1e4f; } uint8_t ADS1115Sensor::get_multiplexer() const { return this->multiplexer_; } void ADS1115Sensor::set_multiplexer(ADS1115Multiplexer multiplexer) { this->multiplexer_ = multiplexer; } uint8_t ADS1115Sensor::get_gain() const { return this->gain_; } void ADS1115Sensor::set_gain(ADS1115Gain gain) { this->gain_ = gain; } +float ADS1115Sensor::sample() { + return this->parent_->request_measurement_(this); +} +void ADS1115Sensor::update() { + float v = this->parent_->request_measurement_(this); + if (!isnan(v)) { + ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v); + this->publish_state(v); + } +} } // namespace ads1115 } // namespace esphome diff --git a/esphome/components/ads1115/ads1115.h b/esphome/components/ads1115/ads1115.h index 863bb247aa..28efc1f5ba 100644 --- a/esphome/components/ads1115/ads1115.h +++ b/esphome/components/ads1115/ads1115.h @@ -3,6 +3,7 @@ #include "esphome/core/component.h" #include "esphome/components/sensor/sensor.h" #include "esphome/components/i2c/i2c.h" +#include "esphome/components/voltage_sampler/voltage_sampler.h" namespace esphome { namespace ads1115 { @@ -38,28 +39,30 @@ class ADS1115Component : public Component, public i2c::I2CDevice { /// HARDWARE_LATE setup priority float get_setup_priority() const override; - protected: /// Helper method to request a measurement from a sensor. - void request_measurement_(ADS1115Sensor *sensor); + float request_measurement_(ADS1115Sensor *sensor); + protected: std::vector sensors_; }; /// Internal holder class that is in instance of Sensor so that the hub can create individual sensors. -class ADS1115Sensor : public sensor::Sensor { +class ADS1115Sensor : public sensor::Sensor, public PollingComponent, + public voltage_sampler::VoltageSampler { public: + ADS1115Sensor(ADS1115Component *parent) : parent_(parent) {} + void update() override; void set_multiplexer(ADS1115Multiplexer multiplexer); void set_gain(ADS1115Gain gain); - // ========== INTERNAL METHODS ========== - // (In most use cases you won't need these) + float sample() override; uint8_t get_multiplexer() const; uint8_t get_gain() const; protected: + ADS1115Component *parent_; ADS1115Multiplexer multiplexer_; ADS1115Gain gain_; - uint32_t update_interval_; }; } // namespace ads1115 diff --git a/esphome/components/ads1115/sensor.py b/esphome/components/ads1115/sensor.py index 4a1d109c23..2fe9b6fa86 100644 --- a/esphome/components/ads1115/sensor.py +++ b/esphome/components/ads1115/sensor.py @@ -1,6 +1,6 @@ import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import sensor +from esphome.components import sensor, voltage_sampler from esphome.components.ads1115 import ADS1115Component from esphome.const import CONF_GAIN, CONF_MULTIPLEXER, ICON_FLASH, UNIT_VOLT, CONF_ID from esphome.py_compat import string_types @@ -40,7 +40,8 @@ def validate_gain(value): return cv.enum(GAIN)(value) -ADS1115Sensor = ads1115_ns.class_('ADS1115Sensor', sensor.Sensor) +ADS1115Sensor = ads1115_ns.class_('ADS1115Sensor', sensor.Sensor, cg.PollingComponent, + voltage_sampler.VoltageSampler) CONF_ADS1115_ID = 'ads1115_id' CONFIG_SCHEMA = sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 3).extend({ @@ -52,11 +53,12 @@ CONFIG_SCHEMA = sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 3).extend({ def to_code(config): - var = cg.new_Pvariable(config[CONF_ID]) + paren = yield cg.get_variable(config[CONF_ADS1115_ID]) + var = cg.new_Pvariable(config[CONF_ID], paren) yield sensor.register_sensor(var, config) + yield cg.register_component(var, config) cg.add(var.set_multiplexer(config[CONF_MULTIPLEXER])) cg.add(var.set_gain(config[CONF_GAIN])) - hub = yield cg.get_variable(config[CONF_ADS1115_ID]) - cg.add(hub.register_sensor(var)) + cg.add(paren.register_sensor(var)) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 2e9b9f6841..a15fe59a6a 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -260,7 +260,6 @@ APIConnection::APIConnection(AsyncClient *client, APIServer *parent) } APIConnection::~APIConnection() { delete this->client_; } void APIConnection::on_error_(int8_t error) { - ESP_LOGD(TAG, "Error from client '%s': %d", this->client_info_.c_str(), error); // disconnect will also be called, nothing to do here this->remove_ = true; } diff --git a/esphome/components/ble_ibeacon/__init__.py b/esphome/components/ble_ibeacon/__init__.py new file mode 100644 index 0000000000..dac5b7c46f --- /dev/null +++ b/esphome/components/ble_ibeacon/__init__.py @@ -0,0 +1,18 @@ +import esphome.config_validation as cv +import esphome.codegen as cg +from esphome.components import esp32_ble_tracker +from esphome.const import CONF_ID + +DEPENDENCIES = ['esp32_ble_tracker'] +ble_ibeacon_ns = cg.esphome_ns.namespace('ble_ibeacon') +IBeaconListener = ble_ibeacon_ns.class_('IBeaconListener', esp32_ble_tracker.ESPBTDeviceListener) + + +CONFIG_SCHEMA = cv.Schema({ + cv.GenerateID(): cv.declare_id(IBeaconListener), +}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + + +def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + yield esp32_ble_tracker.register_ble_device(var, config) diff --git a/esphome/components/ble_presence/binary_sensor.py b/esphome/components/ble_presence/binary_sensor.py index beab5448be..43ec9455d4 100644 --- a/esphome/components/ble_presence/binary_sensor.py +++ b/esphome/components/ble_presence/binary_sensor.py @@ -1,24 +1,24 @@ import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import binary_sensor -from esphome.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESP_BLE_DEVICE_SCHEMA, \ - ESPBTDeviceListener -from esphome.const import CONF_MAC_ADDRESS, CONF_NAME, CONF_ID +from esphome.components import binary_sensor, esp32_ble_tracker +from esphome.const import CONF_MAC_ADDRESS, CONF_ID DEPENDENCIES = ['esp32_ble_tracker'] ble_presence_ns = cg.esphome_ns.namespace('ble_presence') BLEPresenceDevice = ble_presence_ns.class_('BLEPresenceDevice', binary_sensor.BinarySensor, - cg.Component, ESPBTDeviceListener) + cg.Component, esp32_ble_tracker.ESPBTDeviceListener) CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ cv.GenerateID(): cv.declare_id(BLEPresenceDevice), cv.Required(CONF_MAC_ADDRESS): cv.mac_address, -}).extend(ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) def to_code(config): - hub = yield cg.get_variable(config[CONF_ESP32_BLE_ID]) - var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME], hub, config[CONF_MAC_ADDRESS].as_hex) + var = cg.new_Pvariable(config[CONF_ID]) yield cg.register_component(var, config) + yield esp32_ble_tracker.register_ble_device(var, config) yield binary_sensor.register_binary_sensor(var, config) + + cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex)) diff --git a/esphome/components/ble_presence/ble_presence_device.h b/esphome/components/ble_presence/ble_presence_device.h index a5aba35bea..04152d7695 100644 --- a/esphome/components/ble_presence/ble_presence_device.h +++ b/esphome/components/ble_presence/ble_presence_device.h @@ -13,9 +13,9 @@ class BLEPresenceDevice : public binary_sensor::BinarySensor, public esp32_ble_tracker::ESPBTDeviceListener, public Component { public: - BLEPresenceDevice(const std::string &name, esp32_ble_tracker::ESP32BLETracker *parent, uint64_t address) - : binary_sensor::BinarySensor(name), esp32_ble_tracker::ESPBTDeviceListener(parent), address_(address) {} - + void set_address(uint64_t address) { + address_ = address; + } void on_scan_end() override { if (!this->found_) this->publish_state(false); @@ -29,7 +29,6 @@ class BLEPresenceDevice : public binary_sensor::BinarySensor, } return false; } - void setup() override { this->setup_ble(); } void dump_config() override; float get_setup_priority() const override { return setup_priority::DATA; } diff --git a/esphome/components/ble_rssi/ble_rssi_sensor.h b/esphome/components/ble_rssi/ble_rssi_sensor.h index 686e70f82f..633bf1e52f 100644 --- a/esphome/components/ble_rssi/ble_rssi_sensor.h +++ b/esphome/components/ble_rssi/ble_rssi_sensor.h @@ -11,9 +11,9 @@ namespace ble_rssi { class BLERSSISensor : public sensor::Sensor, public esp32_ble_tracker::ESPBTDeviceListener, public Component { public: - BLERSSISensor(const std::string &name, esp32_ble_tracker::ESP32BLETracker *parent, uint64_t address) - : sensor::Sensor(name), esp32_ble_tracker::ESPBTDeviceListener(parent), address_(address) {} - + void set_address(uint64_t address) { + address_ = address; + } void on_scan_end() override { if (!this->found_) this->publish_state(NAN); @@ -27,7 +27,6 @@ class BLERSSISensor : public sensor::Sensor, public esp32_ble_tracker::ESPBTDevi } return false; } - void setup() override { this->setup_ble(); } void dump_config() override; float get_setup_priority() const override { return setup_priority::DATA; } diff --git a/esphome/components/ble_rssi/sensor.py b/esphome/components/ble_rssi/sensor.py index 22e1c82f64..ee8f71632f 100644 --- a/esphome/components/ble_rssi/sensor.py +++ b/esphome/components/ble_rssi/sensor.py @@ -1,24 +1,24 @@ import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import sensor -from esphome.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESPBTDeviceListener, \ - ESP_BLE_DEVICE_SCHEMA -from esphome.const import CONF_MAC_ADDRESS, CONF_NAME, CONF_ID, UNIT_DECIBEL, ICON_SIGNAL +from esphome.components import sensor, esp32_ble_tracker +from esphome.const import CONF_MAC_ADDRESS, CONF_ID, UNIT_DECIBEL, ICON_SIGNAL DEPENDENCIES = ['esp32_ble_tracker'] ble_rssi_ns = cg.esphome_ns.namespace('ble_rssi') BLERSSISensor = ble_rssi_ns.class_('BLERSSISensor', sensor.Sensor, cg.Component, - ESPBTDeviceListener) + esp32_ble_tracker.ESPBTDeviceListener) CONFIG_SCHEMA = sensor.sensor_schema(UNIT_DECIBEL, ICON_SIGNAL, 0).extend({ cv.GenerateID(): cv.declare_id(BLERSSISensor), cv.Required(CONF_MAC_ADDRESS): cv.mac_address, -}).extend(ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) def to_code(config): - hub = yield cg.get_variable(config[CONF_ESP32_BLE_ID]) - var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME], hub, config[CONF_MAC_ADDRESS].as_hex) + var = cg.new_Pvariable(config[CONF_ID]) yield cg.register_component(var, config) + yield esp32_ble_tracker.register_ble_device(var, config) yield sensor.register_sensor(var, config) + + cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex)) diff --git a/esphome/components/esp32_ble_tracker/__init__.py b/esphome/components/esp32_ble_tracker/__init__.py index c77e5cd440..05ca748a99 100644 --- a/esphome/components/esp32_ble_tracker/__init__.py +++ b/esphome/components/esp32_ble_tracker/__init__.py @@ -1,9 +1,10 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_SCAN_INTERVAL, ESP_PLATFORM_ESP32 +from esphome.core import coroutine ESP_PLATFORMS = [ESP_PLATFORM_ESP32] -AUTO_LOAD = ['xiaomi_ble'] +AUTO_LOAD = ['xiaomi_ble', 'ble_ibeacon'] CONF_ESP32_BLE_ID = 'esp32_ble_id' esp32_ble_tracker_ns = cg.esphome_ns.namespace('esp32_ble_tracker') @@ -24,3 +25,10 @@ def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) yield cg.register_component(var, config) cg.add(var.set_scan_interval(config[CONF_SCAN_INTERVAL])) + + +@coroutine +def register_ble_device(var, config): + paren = yield cg.get_variable(config[CONF_ESP32_BLE_ID]) + cg.add(paren.register_listener(var)) + yield var diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index ff88ea79b2..5ef814c2ba 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -201,6 +201,22 @@ void ESP32BLETracker::gap_scan_result(const esp_ble_gap_cb_param_t::ble_scan_res } } +std::string hexencode(const std::string &raw_data) { + char buf[20]; + std::string res; + for (size_t i = 0; i < raw_data.size(); i++) { + if (i + 1 != raw_data.size()) { + sprintf(buf, "0x%02X.", static_cast(raw_data[i])); + } else { + sprintf(buf, "0x%02X ", static_cast(raw_data[i])); + } + res += buf; + } + sprintf(buf, "(%zu)", raw_data.size()); + res += buf; + return res; +} + ESPBTUUID::ESPBTUUID() : uuid_() {} ESPBTUUID ESPBTUUID::from_uint16(uint16_t uuid) { ESPBTUUID ret; @@ -259,12 +275,22 @@ std::string ESPBTUUID::to_string() { return sbuf; } +ESPBLEiBeacon::ESPBLEiBeacon(const uint8_t *data) { memcpy(&this->beacon_data_, data, sizeof(beacon_data_)); } +optional ESPBLEiBeacon::from_manufacturer_data(const std::string &data) { + if (data.size() != 25) + return {}; + if (data[0] != 0x4C || data[1] != 0x00) + return {}; + + return ESPBLEiBeacon(reinterpret_cast(data.data())); +} + void ESPBTDevice::parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param ¶m) { for (uint8_t i = 0; i < ESP_BD_ADDR_LEN; i++) this->address_[i] = param.bda[i]; this->address_type_ = param.ble_addr_type; this->rssi_ = param.rssi; - this->parse_adv(param); + this->parse_adv_(param); #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE ESP_LOGVV(TAG, "Parse Result:"); @@ -287,7 +313,7 @@ void ESPBTDevice::parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_e this->address_[2], this->address_[3], this->address_[4], this->address_[5], address_type); ESP_LOGVV(TAG, " RSSI: %d", this->rssi_); - ESP_LOGVV(TAG, " Name: %s", this->name_.c_str()); + ESP_LOGVV(TAG, " Name: '%s'", this->name_.c_str()); if (this->tx_power_.has_value()) { ESP_LOGVV(TAG, " TX Power: %d", *this->tx_power_); } @@ -300,26 +326,18 @@ void ESPBTDevice::parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_e for (auto uuid : this->service_uuids_) { ESP_LOGVV(TAG, " Service UUID: %s", uuid.to_string().c_str()); } - ESP_LOGVV(TAG, " Manufacturer data: '%s'", this->manufacturer_data_.c_str()); - ESP_LOGVV(TAG, " Service data: '%s'", this->service_data_.c_str()); + ESP_LOGVV(TAG, " Manufacturer data: %s", hexencode(this->manufacturer_data_).c_str()); + ESP_LOGVV(TAG, " Service data: %s", hexencode(this->service_data_).c_str()); if (this->service_data_uuid_.has_value()) { ESP_LOGVV(TAG, " Service Data UUID: %s", this->service_data_uuid_->to_string().c_str()); } - char buffer[200]; - size_t off = 0; - for (uint8_t i = 0; i < param.adv_data_len; i++) { - int ret = snprintf(buffer + off, sizeof(buffer) - off, "%02X.", param.ble_adv[i]); - if (ret < 0) { - break; - } - off += ret; - } - ESP_LOGVV(TAG, "Adv data: %s (%u bytes)", buffer, param.adv_data_len); + ESP_LOGVV(TAG, "Adv data: %s", + hexencode(std::string(reinterpret_cast(param.ble_adv), param.adv_data_len)).c_str()); #endif } -void ESPBTDevice::parse_adv(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param ¶m) { +void ESPBTDevice::parse_adv_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param ¶m) { size_t offset = 0; const uint8_t *payload = param.ble_adv; uint8_t len = param.adv_data_len; @@ -472,8 +490,6 @@ void ESP32BLETracker::print_bt_device_info(const ESPBTDevice &device) { } } -void ESPBTDeviceListener::setup_ble() { this->parent_->add_listener(this); } - } // namespace esp32_ble_tracker } // namespace esphome diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index 29927ea53c..a2c68063e7 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -31,12 +31,31 @@ class ESPBTUUID { esp_bt_uuid_t uuid_; }; +class ESPBLEiBeacon { + public: + ESPBLEiBeacon(const uint8_t *data); + static optional from_manufacturer_data(const std::string &data); + + uint16_t get_major() { return reverse_bits_16(this->beacon_data_.major); } + uint16_t get_minor() { return reverse_bits_16(this->beacon_data_.minor); } + int8_t get_signal_power() { return this->beacon_data_.signal_power; } + ESPBTUUID get_uuid() { return ESPBTUUID::from_raw(this->beacon_data_.proximity_uuid); } + + protected: + struct { + uint16_t manufacturer_id; + uint8_t sub_type; + uint8_t proximity_uuid[16]; + uint16_t major; + uint16_t minor; + int8_t signal_power; + } PACKED beacon_data_; +}; + class ESPBTDevice { public: void parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param ¶m); - void parse_adv(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param ¶m); - std::string address_str() const; uint64_t address_uint64() const; @@ -51,8 +70,13 @@ class ESPBTDevice { const std::string &get_manufacturer_data() const; const std::string &get_service_data() const; const optional &get_service_data_uuid() const; + const optional get_ibeacon() const { + return ESPBLEiBeacon::from_manufacturer_data(this->manufacturer_data_); + } protected: + void parse_adv_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param ¶m); + esp_bd_addr_t address_{ 0, }; @@ -72,28 +96,30 @@ class ESP32BLETracker; class ESPBTDeviceListener { public: - ESPBTDeviceListener(ESP32BLETracker *parent) : parent_(parent) {} - void setup_ble(); virtual void on_scan_end() {} virtual bool parse_device(const ESPBTDevice &device) = 0; + void set_parent(ESP32BLETracker *parent) { + parent_ = parent; + } protected: - ESP32BLETracker *parent_; + ESP32BLETracker *parent_{nullptr}; }; class ESP32BLETracker : public Component { public: void set_scan_interval(uint32_t scan_interval); - // ========== INTERNAL METHODS ========== - // (In most use cases you won't need these) /// Setup the FreeRTOS task and the Bluetooth stack. void setup() override; void dump_config() override; void loop() override; - void add_listener(ESPBTDeviceListener *listener) { this->listeners_.push_back(listener); } + void register_listener(ESPBTDeviceListener *listener) { + listener->set_parent(this); + this->listeners_.push_back(listener); + } void print_bt_device_info(const ESPBTDevice &device); diff --git a/esphome/components/light/automation.h b/esphome/components/light/automation.h index f907c70963..af295df369 100644 --- a/esphome/components/light/automation.h +++ b/esphome/components/light/automation.h @@ -112,7 +112,7 @@ template class AddressableSet : public Action { void play(Ts... x) override { auto *out = (AddressableLight *) this->parent_->get_output(); int32_t range_from = this->range_from_.value_or(x..., 0); - int32_t range_to = this->range_to_.value_or(x..., out->size()); + int32_t range_to = this->range_to_.value_or(x..., out->size() - 1) + 1; auto range = out->range(range_from, range_to); if (this->red_.has_value()) range.set_red(this->red_.value(x...)); diff --git a/esphome/components/light/automation.py b/esphome/components/light/automation.py index 4718a22052..42a8319728 100644 --- a/esphome/components/light/automation.py +++ b/esphome/components/light/automation.py @@ -3,8 +3,9 @@ import esphome.config_validation as cv from esphome import automation from esphome.const import CONF_ID, CONF_TRANSITION_LENGTH, CONF_STATE, CONF_FLASH_LENGTH, \ CONF_EFFECT, CONF_BRIGHTNESS, CONF_RED, CONF_GREEN, CONF_BLUE, CONF_WHITE, \ - CONF_COLOR_TEMPERATURE -from .types import DimRelativeAction, ToggleAction, LightState, LightControlAction + CONF_COLOR_TEMPERATURE, CONF_RANGE_FROM, CONF_RANGE_TO +from .types import DimRelativeAction, ToggleAction, LightState, LightControlAction, \ + AddressableLightState, AddressableSet @automation.register_action('light.toggle', ToggleAction, automation.maybe_simple_id({ @@ -87,7 +88,7 @@ def light_control_to_code(config, action_id, template_arg, args): CONF_RELATIVE_BRIGHTNESS = 'relative_brightness' LIGHT_DIM_RELATIVE_ACTION_SCHEMA = cv.Schema({ cv.Required(CONF_ID): cv.use_id(LightState), - cv.Required(CONF_RELATIVE_BRIGHTNESS): cv.templatable(cv.percentage), + cv.Required(CONF_RELATIVE_BRIGHTNESS): cv.templatable(cv.possibly_negative_percentage), cv.Optional(CONF_TRANSITION_LENGTH): cv.templatable(cv.positive_time_period_milliseconds), }) @@ -103,3 +104,41 @@ def light_dim_relative_to_code(config, action_id, template_arg, args): templ = yield cg.templatable(config[CONF_TRANSITION_LENGTH], args, cg.uint32) cg.add(var.set_transition_length(templ)) yield var + + +LIGHT_ADDRESSABLE_SET_ACTION_SCHEMA = cv.Schema({ + cv.Required(CONF_ID): cv.use_id(AddressableLightState), + cv.Optional(CONF_RANGE_FROM): cv.templatable(cv.positive_int), + cv.Optional(CONF_RANGE_TO): cv.templatable(cv.positive_int), + cv.Optional(CONF_RED): cv.templatable(cv.percentage), + cv.Optional(CONF_GREEN): cv.templatable(cv.percentage), + cv.Optional(CONF_BLUE): cv.templatable(cv.percentage), + cv.Optional(CONF_WHITE): cv.templatable(cv.percentage), +}) + + +@automation.register_action('light.addressable_set', AddressableSet, + LIGHT_ADDRESSABLE_SET_ACTION_SCHEMA) +def light_addressable_set_to_code(config, action_id, template_arg, args): + paren = yield cg.get_variable(config[CONF_ID]) + var = cg.new_Pvariable(action_id, template_arg, paren) + if CONF_RANGE_FROM in config: + templ = yield cg.templatable(config[CONF_RANGE_FROM], args, cg.int32) + cg.add(var.set_range_from(templ)) + if CONF_RANGE_TO in config: + templ = yield cg.templatable(config[CONF_RANGE_TO], args, cg.int32) + cg.add(var.set_range_to(templ)) + rgbw_to_exp = lambda x: int(round(x * 255)) + if CONF_RED in config: + templ = yield cg.templatable(config[CONF_RED], args, cg.uint8, to_exp=rgbw_to_exp) + cg.add(var.set_red(templ)) + if CONF_GREEN in config: + templ = yield cg.templatable(config[CONF_GREEN], args, cg.uint8, to_exp=rgbw_to_exp) + cg.add(var.set_green(templ)) + if CONF_BLUE in config: + templ = yield cg.templatable(config[CONF_BLUE], args, cg.uint8, to_exp=rgbw_to_exp) + cg.add(var.set_blue(templ)) + if CONF_WHITE in config: + templ = yield cg.templatable(config[CONF_WHITE], args, cg.uint8, to_exp=rgbw_to_exp) + cg.add(var.set_white(templ)) + yield var diff --git a/esphome/components/light/types.py b/esphome/components/light/types.py index c9f638a4a4..33ba759df0 100644 --- a/esphome/components/light/types.py +++ b/esphome/components/light/types.py @@ -15,6 +15,7 @@ LightColorValues = light_ns.class_('LightColorValues') ToggleAction = light_ns.class_('ToggleAction', automation.Action) LightControlAction = light_ns.class_('LightControlAction', automation.Action) DimRelativeAction = light_ns.class_('DimRelativeAction', automation.Action) +AddressableSet = light_ns.class_('AddressableSet', automation.Action) # Effects LightEffect = light_ns.class_('LightEffect') diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 9e351d0b01..27141f93c2 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -71,6 +71,7 @@ def validate_local_no_higher_than_global(value): Logger = logger_ns.class_('Logger', cg.Component) +CONF_ESP8266_STORE_LOG_STRINGS_IN_FLASH = 'esp8266_store_log_strings_in_flash' CONFIG_SCHEMA = cv.All(cv.Schema({ cv.GenerateID(): cv.declare_id(Logger), cv.Optional(CONF_BAUD_RATE, default=115200): cv.positive_int, @@ -79,7 +80,10 @@ CONFIG_SCHEMA = cv.All(cv.Schema({ cv.Optional(CONF_LEVEL, default='DEBUG'): is_log_level, cv.Optional(CONF_LOGS, default={}): cv.Schema({ cv.string: is_log_level, - }) + }), + + cv.SplitDefault(CONF_ESP8266_STORE_LOG_STRINGS_IN_FLASH, esp8266=True): + cv.All(cv.only_on_esp8266, cv.boolean), }).extend(cv.COMPONENT_SCHEMA), validate_local_no_higher_than_global) @@ -126,7 +130,7 @@ def to_code(config): cg.add_build_flag('-DCORE_DEBUG_LEVEL=5') if CORE.is_esp32 and is_at_least_very_verbose: cg.add_build_flag('-DENABLE_I2C_DEBUG_BUFFER') - if CORE.is_esp8266: + if config.get(CONF_ESP8266_STORE_LOG_STRINGS_IN_FLASH): cg.add_build_flag('-DUSE_STORE_LOG_STR_IN_FLASH') # Register at end for safe mode diff --git a/esphome/components/mpu6050/mpu6050.cpp b/esphome/components/mpu6050/mpu6050.cpp index 68ec35f6c0..deba316a7f 100644 --- a/esphome/components/mpu6050/mpu6050.cpp +++ b/esphome/components/mpu6050/mpu6050.cpp @@ -99,17 +99,18 @@ void MPU6050Component::dump_config() { void MPU6050Component::update() { ESP_LOGV(TAG, " Updating MPU6050..."); - uint16_t data[7]; - if (!this->read_bytes_16(MPU6050_REGISTER_ACCEL_XOUT_H, data, 7)) { + uint16_t raw_data[7]; + if (!this->read_bytes_16(MPU6050_REGISTER_ACCEL_XOUT_H, raw_data, 7)) { this->status_set_warning(); return; } + auto *data = reinterpret_cast(raw_data); float accel_x = data[0] * MPU6050_RANGE_PER_DIGIT_2G * GRAVITY_EARTH; float accel_y = data[1] * MPU6050_RANGE_PER_DIGIT_2G * GRAVITY_EARTH; float accel_z = data[2] * MPU6050_RANGE_PER_DIGIT_2G * GRAVITY_EARTH; - float temperature = data[3] / 340.0f + 36.53f; + float temperature = raw_data[3] / 340.0f + 36.53f; float gyro_x = data[4] * MPU6050_SCALE_DPS_PER_DIGIT_2000; float gyro_y = data[5] * MPU6050_SCALE_DPS_PER_DIGIT_2000; diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index a233468762..0fe0fc6bca 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -51,8 +51,6 @@ sensor_ns = cg.esphome_ns.namespace('sensor') Sensor = sensor_ns.class_('Sensor', cg.Nameable) SensorPtr = Sensor.operator('ptr') -PollingSensorComponent = sensor_ns.class_('PollingSensorComponent', cg.PollingComponent, Sensor) - # Triggers SensorStateTrigger = sensor_ns.class_('SensorStateTrigger', automation.Trigger.template(cg.float_)) SensorRawStateTrigger = sensor_ns.class_('SensorRawStateTrigger', diff --git a/esphome/components/time/real_time_clock.cpp b/esphome/components/time/real_time_clock.cpp index b2966cd8e0..f20a9fcaa2 100644 --- a/esphome/components/time/real_time_clock.cpp +++ b/esphome/components/time/real_time_clock.cpp @@ -11,16 +11,6 @@ namespace time { static const char *TAG = "time"; RealTimeClock::RealTimeClock() = default; -ESPTime RealTimeClock::now() { - time_t t = ::time(nullptr); - struct tm *c_tm = ::localtime(&t); - return ESPTime::from_tm(c_tm, t); -} -ESPTime RealTimeClock::utcnow() { - time_t t = ::time(nullptr); - struct tm *c_tm = ::gmtime(&t); - return ESPTime::from_tm(c_tm, t); -} void RealTimeClock::call_setup() { this->setup_internal_(); setenv("TZ", this->timezone_.c_str(), 1); @@ -44,7 +34,7 @@ size_t ESPTime::strftime(char *buffer, size_t buffer_len, const char *format) { struct tm c_tm = this->to_c_tm(); return ::strftime(buffer, buffer_len, format, &c_tm); } -ESPTime ESPTime::from_tm(struct tm *c_tm, time_t c_time) { +ESPTime ESPTime::from_c_tm(struct tm *c_tm, time_t c_time) { return ESPTime{.second = uint8_t(c_tm->tm_sec), .minute = uint8_t(c_tm->tm_min), .hour = uint8_t(c_tm->tm_hour), diff --git a/esphome/components/time/real_time_clock.h b/esphome/components/time/real_time_clock.h index 21d63900b6..f416938717 100644 --- a/esphome/components/time/real_time_clock.h +++ b/esphome/components/time/real_time_clock.h @@ -52,7 +52,26 @@ struct ESPTime { bool in_range() const; - static ESPTime from_tm(struct tm *c_tm, time_t c_time); + static ESPTime from_c_tm(struct tm *c_tm, time_t c_time); + + /** Convert an epoch timestamp to an ESPTime instance of local time. + * + * @param epoch Seconds since 1st January 1970. In UTC. + * @return The generated ESPTime + */ + static ESPTime from_epoch_local(time_t epoch) { + struct tm *c_tm = ::localtime(&epoch); + return ESPTime::from_c_tm(c_tm, epoch); + } + /** Convert an epoch timestamp to an ESPTime instance of UTC time. + * + * @param epoch Seconds since 1st January 1970. In UTC. + * @return The generated ESPTime + */ + static ESPTime from_epoch_utc(time_t epoch) { + struct tm *c_tm = ::gmtime(&epoch); + return ESPTime::from_c_tm(c_tm, epoch); + } struct tm to_c_tm(); @@ -81,10 +100,19 @@ class RealTimeClock : public Component { std::string get_timezone() { return this->timezone_; } /// Get the time in the currently defined timezone. - ESPTime now(); + ESPTime now() { + return ESPTime::from_epoch_utc(this->timestamp_now()); + } /// Get the time without any time zone or DST corrections. - ESPTime utcnow(); + ESPTime utcnow() { + return ESPTime::from_epoch_local(this->timestamp_now()); + } + + /// Get the current time as the UTC epoch since January 1st 1970. + time_t timestamp_now() { + return ::time(nullptr); + } void call_setup() override; diff --git a/esphome/components/voltage_sampler/__init__.py b/esphome/components/voltage_sampler/__init__.py new file mode 100644 index 0000000000..64161205d8 --- /dev/null +++ b/esphome/components/voltage_sampler/__init__.py @@ -0,0 +1,4 @@ +import esphome.codegen as cg + +voltage_sampler_ns = cg.esphome_ns.namespace('voltage_sampler') +VoltageSampler = voltage_sampler_ns.class_('VoltageSampler') diff --git a/esphome/components/voltage_sampler/voltage_sampler.h b/esphome/components/voltage_sampler/voltage_sampler.h new file mode 100644 index 0000000000..d2e74d33bc --- /dev/null +++ b/esphome/components/voltage_sampler/voltage_sampler.h @@ -0,0 +1,16 @@ +#pragma once + +#include "esphome/core/component.h" + +namespace esphome { +namespace voltage_sampler { + +/// Abstract interface for components to request voltage (usually ADC readings) +class VoltageSampler { + public: + /// Get a voltage reading, in V. + virtual float sample() = 0; +}; + +} // namespace voltage_sampler +} // namespace esphome diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 28d911606b..35735e5f08 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -468,10 +468,6 @@ std::string WiFiComponent::format_mac_addr(const uint8_t *mac) { sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); return buf; } -void WiFiComponent::on_safe_shutdown() { - // Disable WiFi interface on shutdown - this->wifi_mode_(false, false); -} bool sta_field_equal(const uint8_t *field_a, const uint8_t *field_b, int len) { for (int i = 0; i < len; i++) { diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index a9e67f23c6..8e6418791c 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -164,8 +164,6 @@ class WiFiComponent : public Component { /// Reconnect WiFi if required. void loop() override; - void on_safe_shutdown() override; - bool has_sta() const; bool has_ap() const; diff --git a/esphome/components/wifi/wifi_component_esp32.cpp b/esphome/components/wifi/wifi_component_esp32.cpp index 1edfe11ce2..f50acee614 100644 --- a/esphome/components/wifi/wifi_component_esp32.cpp +++ b/esphome/components/wifi/wifi_component_esp32.cpp @@ -173,6 +173,8 @@ bool WiFiComponent::wifi_sta_connect_(WiFiAP ap) { return false; } + this->wifi_apply_hostname_(); + err = esp_wifi_connect(); if (err != ESP_OK) { ESP_LOGW(TAG, "esp_wifi_connect failed! %d", err); diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 5030e87e25..a2c9ac2551 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -196,6 +196,8 @@ bool WiFiComponent::wifi_sta_connect_(WiFiAP ap) { return false; } + this->wifi_apply_hostname_(); + ETS_UART_INTR_DISABLE(); ret = wifi_station_connect(); ETS_UART_INTR_ENABLE(); diff --git a/esphome/components/xiaomi_ble/__init__.py b/esphome/components/xiaomi_ble/__init__.py index ef5df12cd9..2b36090293 100644 --- a/esphome/components/xiaomi_ble/__init__.py +++ b/esphome/components/xiaomi_ble/__init__.py @@ -1,20 +1,18 @@ import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESPBTDeviceListener, \ - ESP_BLE_DEVICE_SCHEMA +from esphome.components import esp32_ble_tracker from esphome.const import CONF_ID DEPENDENCIES = ['esp32_ble_tracker'] xiaomi_ble_ns = cg.esphome_ns.namespace('xiaomi_ble') -XiaomiListener = xiaomi_ble_ns.class_('XiaomiListener', cg.Component, ESPBTDeviceListener) +XiaomiListener = xiaomi_ble_ns.class_('XiaomiListener', esp32_ble_tracker.ESPBTDeviceListener) CONFIG_SCHEMA = cv.Schema({ cv.GenerateID(): cv.declare_id(XiaomiListener), -}).extend(ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) def to_code(config): - hub = yield cg.get_variable(config[CONF_ESP32_BLE_ID]) - var = cg.new_Pvariable(config[CONF_ID], hub) - yield cg.register_component(var, config) + var = cg.new_Pvariable(config[CONF_ID]) + yield esp32_ble_tracker.register_ble_device(var, config) diff --git a/esphome/components/xiaomi_ble/xiaomi_ble.cpp b/esphome/components/xiaomi_ble/xiaomi_ble.cpp index 8addbe6401..7431b84491 100644 --- a/esphome/components/xiaomi_ble/xiaomi_ble.cpp +++ b/esphome/components/xiaomi_ble/xiaomi_ble.cpp @@ -138,8 +138,6 @@ bool XiaomiListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device) return true; } -void XiaomiListener::setup() { this->setup_ble(); } -XiaomiListener::XiaomiListener(esp32_ble_tracker::ESP32BLETracker *parent) : ESPBTDeviceListener(parent) {} } // namespace xiaomi_ble } // namespace esphome diff --git a/esphome/components/xiaomi_ble/xiaomi_ble.h b/esphome/components/xiaomi_ble/xiaomi_ble.h index df70fd2fc5..058a89927b 100644 --- a/esphome/components/xiaomi_ble/xiaomi_ble.h +++ b/esphome/components/xiaomi_ble/xiaomi_ble.h @@ -22,11 +22,9 @@ bool parse_xiaomi_data_byte(uint8_t data_type, const uint8_t *data, uint8_t data optional parse_xiaomi(const esp32_ble_tracker::ESPBTDevice &device); -class XiaomiListener : public Component, public esp32_ble_tracker::ESPBTDeviceListener { +class XiaomiListener : public esp32_ble_tracker::ESPBTDeviceListener { public: - XiaomiListener(esp32_ble_tracker::ESP32BLETracker *parent); bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override; - void setup() override; }; } // namespace xiaomi_ble diff --git a/esphome/components/xiaomi_miflora/sensor.py b/esphome/components/xiaomi_miflora/sensor.py index f6b44f9239..8be06a93f3 100644 --- a/esphome/components/xiaomi_miflora/sensor.py +++ b/esphome/components/xiaomi_miflora/sensor.py @@ -1,8 +1,6 @@ import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import sensor -from esphome.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESPBTDeviceListener, \ - ESP_BLE_DEVICE_SCHEMA +from esphome.components import sensor, esp32_ble_tracker from esphome.const import CONF_BATTERY_LEVEL, CONF_MAC_ADDRESS, CONF_TEMPERATURE, \ UNIT_CELSIUS, ICON_THERMOMETER, UNIT_PERCENT, ICON_WATER_PERCENT, ICON_BATTERY, CONF_ID, \ CONF_MOISTURE, CONF_ILLUMINANCE, ICON_BRIGHTNESS_5, UNIT_LUX, CONF_CONDUCTIVITY, \ @@ -12,7 +10,8 @@ DEPENDENCIES = ['esp32_ble_tracker'] AUTO_LOAD = ['xiaomi_ble'] xiaomi_miflora_ns = cg.esphome_ns.namespace('xiaomi_miflora') -XiaomiMiflora = xiaomi_miflora_ns.class_('XiaomiMiflora', ESPBTDeviceListener, cg.Component) +XiaomiMiflora = xiaomi_miflora_ns.class_('XiaomiMiflora', esp32_ble_tracker.ESPBTDeviceListener, + cg.Component) CONFIG_SCHEMA = cv.Schema({ cv.GenerateID(): cv.declare_id(XiaomiMiflora), @@ -23,13 +22,15 @@ CONFIG_SCHEMA = cv.Schema({ cv.Optional(CONF_CONDUCTIVITY): sensor.sensor_schema(UNIT_MICROSIEMENS_PER_CENTIMETER, ICON_FLOWER, 0), cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(UNIT_PERCENT, ICON_BATTERY, 0), -}).extend(ESP_BLE_DEVICE_SCHEMA) +}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) def to_code(config): - hub = yield cg.get_variable(config[CONF_ESP32_BLE_ID]) - var = cg.new_Pvariable(config[CONF_ID], hub, config[CONF_MAC_ADDRESS].as_hex) + var = cg.new_Pvariable(config[CONF_ID]) yield cg.register_component(var, config) + yield esp32_ble_tracker.register_ble_device(var, config) + + cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex)) if CONF_TEMPERATURE in config: sens = yield sensor.new_sensor(config[CONF_TEMPERATURE]) diff --git a/esphome/components/xiaomi_miflora/xiaomi_miflora.h b/esphome/components/xiaomi_miflora/xiaomi_miflora.h index 987e0cc409..7a1459b3b9 100644 --- a/esphome/components/xiaomi_miflora/xiaomi_miflora.h +++ b/esphome/components/xiaomi_miflora/xiaomi_miflora.h @@ -12,8 +12,9 @@ namespace xiaomi_miflora { class XiaomiMiflora : public Component, public esp32_ble_tracker::ESPBTDeviceListener { public: - XiaomiMiflora(esp32_ble_tracker::ESP32BLETracker *parent, uint64_t address) - : ESPBTDeviceListener(parent), address_(address) {} + void set_address(uint64_t address) { + address_ = address; + } bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override { if (device.address_uint64() != this->address_) diff --git a/esphome/components/xiaomi_mijia/sensor.py b/esphome/components/xiaomi_mijia/sensor.py index ef68443304..995a6cbf25 100644 --- a/esphome/components/xiaomi_mijia/sensor.py +++ b/esphome/components/xiaomi_mijia/sensor.py @@ -1,8 +1,6 @@ import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import sensor -from esphome.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESPBTDeviceListener, \ - ESP_BLE_DEVICE_SCHEMA +from esphome.components import sensor, esp32_ble_tracker from esphome.const import CONF_BATTERY_LEVEL, CONF_HUMIDITY, CONF_MAC_ADDRESS, CONF_TEMPERATURE, \ UNIT_CELSIUS, ICON_THERMOMETER, UNIT_PERCENT, ICON_WATER_PERCENT, ICON_BATTERY, CONF_ID @@ -10,7 +8,8 @@ DEPENDENCIES = ['esp32_ble_tracker'] AUTO_LOAD = ['xiaomi_ble'] xiaomi_mijia_ns = cg.esphome_ns.namespace('xiaomi_mijia') -XiaomiMijia = xiaomi_mijia_ns.class_('XiaomiMijia', ESPBTDeviceListener, cg.Component) +XiaomiMijia = xiaomi_mijia_ns.class_('XiaomiMijia', esp32_ble_tracker.ESPBTDeviceListener, + cg.Component) CONFIG_SCHEMA = cv.Schema({ cv.GenerateID(): cv.declare_id(XiaomiMijia), @@ -18,13 +17,15 @@ CONFIG_SCHEMA = cv.Schema({ cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1), cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 1), cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(UNIT_PERCENT, ICON_BATTERY, 0), -}).extend(ESP_BLE_DEVICE_SCHEMA) +}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) def to_code(config): - hub = yield cg.get_variable(config[CONF_ESP32_BLE_ID]) - var = cg.new_Pvariable(config[CONF_ID], hub, config[CONF_MAC_ADDRESS].as_hex) + var = cg.new_Pvariable(config[CONF_ID]) yield cg.register_component(var, config) + yield esp32_ble_tracker.register_ble_device(var, config) + + cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex)) if CONF_TEMPERATURE in config: sens = yield sensor.new_sensor(config[CONF_TEMPERATURE]) diff --git a/esphome/components/xiaomi_mijia/xiaomi_mijia.h b/esphome/components/xiaomi_mijia/xiaomi_mijia.h index e5b947e6b2..6ed066f3be 100644 --- a/esphome/components/xiaomi_mijia/xiaomi_mijia.h +++ b/esphome/components/xiaomi_mijia/xiaomi_mijia.h @@ -12,8 +12,9 @@ namespace xiaomi_mijia { class XiaomiMijia : public Component, public esp32_ble_tracker::ESPBTDeviceListener { public: - XiaomiMijia(esp32_ble_tracker::ESP32BLETracker *parent, uint64_t address) - : ESPBTDeviceListener(parent), address_(address) {} + void set_address(uint64_t address) { + address_ = address; + } bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override { if (device.address_uint64() != this->address_) diff --git a/esphome/const.py b/esphome/const.py index 10e2781b44..fa9bae4304 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -317,6 +317,8 @@ CONF_PULSE_LENGTH = 'pulse_length' CONF_QOS = 'qos' CONF_RANDOM = 'random' CONF_RANGE = 'range' +CONF_RANGE_FROM = 'range_from' +CONF_RANGE_TO = 'range_to' CONF_RATE = 'rate' CONF_RAW = 'raw' CONF_REBOOT_TIMEOUT = 'reboot_timeout' diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index c9ee402a39..cc046a6962 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -18,6 +18,7 @@ #define HOT __attribute__((hot)) #define ESPDEPRECATED(msg) __attribute__((deprecated(msg))) #define ALWAYS_INLINE __attribute__((always_inline)) +#define PACKED __attribute__((packed)) namespace esphome { diff --git a/script/build_compile_commands.py b/script/build_compile_commands.py new file mode 100755 index 0000000000..91eb75bd00 --- /dev/null +++ b/script/build_compile_commands.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +import codecs +import json +import os +import re +import sys + +root_path = os.path.abspath(os.path.normpath(os.path.join(__file__, '..', '..'))) +basepath = os.path.join(root_path, 'esphome') + + +def walk_files(path): + for root, _, files in os.walk(path): + for name in files: + yield os.path.join(root, name) + + +def shlex_quote(s): + if not s: + return u"''" + if re.search(r'[^\w@%+=:,./-]', s) is None: + return s + + return u"'" + s.replace(u"'", u"'\"'\"'") + u"'" + + +def build_compile_commands(): + gcc_flags_json = os.path.join(root_path, '.gcc-flags.json') + if not os.path.isfile(gcc_flags_json): + print("Could not find {} file which is required for clang-tidy.") + print('Please run "pio init --ide atom" in the root esphome folder to generate that file.') + sys.exit(1) + with codecs.open(gcc_flags_json, 'r', encoding='utf-8') as f: + gcc_flags = json.load(f) + exec_path = gcc_flags['execPath'] + include_paths = gcc_flags['gccIncludePaths'].split(',') + includes = ['-I{}'.format(p) for p in include_paths] + cpp_flags = gcc_flags['gccDefaultCppFlags'].split(' ') + defines = [flag for flag in cpp_flags if flag.startswith('-D')] + command = [exec_path] + command.extend(includes) + command.extend(defines) + command.append('-std=gnu++11') + command.append('-Wall') + command.append('-Wno-delete-non-virtual-dtor') + command.append('-Wno-unused-variable') + command.append('-Wunreachable-code') + + source_files = [] + for path in walk_files(basepath): + filetypes = ('.cpp',) + ext = os.path.splitext(path)[1] + if ext in filetypes: + source_files.append(os.path.abspath(path)) + source_files.sort() + compile_commands = [{ + 'directory': root_path, + 'command': ' '.join(shlex_quote(x) for x in (command + ['-o', p + '.o', '-c', p])), + 'file': p + } for p in source_files] + compile_commands_json = os.path.join(root_path, 'compile_commands.json') + if os.path.isfile(compile_commands_json): + with codecs.open(compile_commands_json, 'r', encoding='utf-8') as f: + try: + if json.load(f) == compile_commands: + return + except: + pass + with codecs.open(compile_commands_json, 'w', encoding='utf-8') as f: + json.dump(compile_commands, f, indent=2) + + +def main(): + build_compile_commands() + print("Done.") + + +if __name__ == '__main__': + main() diff --git a/script/clang-tidy.py b/script/clang-tidy.py index ae850d427f..5b6129b35a 100755 --- a/script/clang-tidy.py +++ b/script/clang-tidy.py @@ -45,6 +45,8 @@ def run_tidy(args, tmpdir, queue, lock, failed_files): invocation.append('-p=.') if args.quiet: invocation.append('-quiet') + for arg in ['-Wfor-loop-analysis', '-Wshadow-field', '-Wshadow-field-in-constructor']: + invocation.append('-extra-arg={}'.format(arg)) invocation.append(os.path.abspath(path)) invocation_s = ' '.join(shlex_quote(x) for x in invocation) @@ -135,9 +137,6 @@ def build_compile_commands(): command.append('-Wall') command.append('-Wno-delete-non-virtual-dtor') command.append('-Wno-unused-variable') - command.append('-Wfor-loop-analysis') - command.append('-Wshadow-field') - command.append('-Wshadow-field-in-constructor') command.append('-Wunreachable-code') source_files = [] From 1ee85295f219e3de9f843f7efea1dad0844932b0 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Wed, 8 May 2019 10:17:08 +0200 Subject: [PATCH 07/17] Lint --- esphome/components/ads1115/ads1115.cpp | 8 ++--- esphome/components/ads1115/ads1115.h | 2 +- esphome/components/bh1750/sensor.py | 2 +- esphome/components/duty_cycle/sensor.py | 2 +- esphome/components/esp32_hall/esp32_hall.h | 5 +-- esphome/components/esp32_hall/sensor.py | 10 +++--- esphome/components/hx711/sensor.py | 2 +- esphome/components/light/automation.py | 5 ++- esphome/components/max31855/sensor.py | 3 +- esphome/components/max6675/sensor.py | 2 +- .../neopixelbus/neopixelbus_light.h | 4 +-- .../components/partition/light_partition.h | 33 ++++++++++--------- esphome/components/pulse_counter/sensor.py | 2 +- esphome/components/pulse_width/sensor.py | 2 +- .../components/template/sensor/__init__.py | 2 +- esphome/components/tsl2561/sensor.py | 3 +- esphome/components/ultrasonic/sensor.py | 2 +- esphome/components/uptime/sensor.py | 2 +- esphome/components/wifi_signal/sensor.py | 2 +- script/build_compile_commands.py | 21 ++++++++++++ script/clang-tidy.py | 6 ---- 21 files changed, 68 insertions(+), 52 deletions(-) diff --git a/esphome/components/ads1115/ads1115.cpp b/esphome/components/ads1115/ads1115.cpp index a6fd2d76cd..924cd1e3e4 100644 --- a/esphome/components/ads1115/ads1115.cpp +++ b/esphome/components/ads1115/ads1115.cpp @@ -60,7 +60,7 @@ void ADS1115Component::setup() { for (auto *sensor : this->sensors_) { this->set_interval(sensor->get_name(), sensor->update_interval(), [this, sensor] { - this->request_measurement_(sensor); + this->request_measurement(sensor); }); } } @@ -78,7 +78,7 @@ void ADS1115Component::dump_config() { } } float ADS1115Component::get_setup_priority() const { return setup_priority::DATA; } -float ADS1115Component::request_measurement_(ADS1115Sensor *sensor) { +float ADS1115Component::request_measurement(ADS1115Sensor *sensor) { uint16_t config; if (!this->read_byte_16(ADS1115_REGISTER_CONFIG, &config)) { this->status_set_warning(); @@ -154,10 +154,10 @@ void ADS1115Sensor::set_multiplexer(ADS1115Multiplexer multiplexer) { this->mult uint8_t ADS1115Sensor::get_gain() const { return this->gain_; } void ADS1115Sensor::set_gain(ADS1115Gain gain) { this->gain_ = gain; } float ADS1115Sensor::sample() { - return this->parent_->request_measurement_(this); + return this->parent_->request_measurement(this); } void ADS1115Sensor::update() { - float v = this->parent_->request_measurement_(this); + float v = this->parent_->request_measurement(this); if (!isnan(v)) { ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v); this->publish_state(v); diff --git a/esphome/components/ads1115/ads1115.h b/esphome/components/ads1115/ads1115.h index 28efc1f5ba..f9d00f9b19 100644 --- a/esphome/components/ads1115/ads1115.h +++ b/esphome/components/ads1115/ads1115.h @@ -40,7 +40,7 @@ class ADS1115Component : public Component, public i2c::I2CDevice { float get_setup_priority() const override; /// Helper method to request a measurement from a sensor. - float request_measurement_(ADS1115Sensor *sensor); + float request_measurement(ADS1115Sensor *sensor); protected: std::vector sensors_; diff --git a/esphome/components/bh1750/sensor.py b/esphome/components/bh1750/sensor.py index 27ee3d1b85..b3ce0eaf88 100644 --- a/esphome/components/bh1750/sensor.py +++ b/esphome/components/bh1750/sensor.py @@ -13,7 +13,7 @@ BH1750_RESOLUTIONS = { 0.5: BH1750Resolution.BH1750_RESOLUTION_0P5_LX, } -BH1750Sensor = bh1750_ns.class_('BH1750Sensor', sensor.PollingSensorComponent, i2c.I2CDevice) +BH1750Sensor = bh1750_ns.class_('BH1750Sensor', sensor.Sensor, cg.PollingComponent, i2c.I2CDevice) CONFIG_SCHEMA = sensor.sensor_schema(UNIT_LUX, ICON_BRIGHTNESS_5, 1).extend({ cv.GenerateID(): cv.declare_id(BH1750Sensor), diff --git a/esphome/components/duty_cycle/sensor.py b/esphome/components/duty_cycle/sensor.py index d60ff0d8be..51d99aae6a 100644 --- a/esphome/components/duty_cycle/sensor.py +++ b/esphome/components/duty_cycle/sensor.py @@ -5,7 +5,7 @@ from esphome.components import sensor from esphome.const import CONF_ID, CONF_PIN, UNIT_PERCENT, ICON_PERCENT duty_cycle_ns = cg.esphome_ns.namespace('duty_cycle') -DutyCycleSensor = duty_cycle_ns.class_('DutyCycleSensor', sensor.PollingSensorComponent) +DutyCycleSensor = duty_cycle_ns.class_('DutyCycleSensor', sensor.Sensor, cg.PollingComponent) CONFIG_SCHEMA = sensor.sensor_schema(UNIT_PERCENT, ICON_PERCENT, 1).extend({ cv.GenerateID(): cv.declare_id(DutyCycleSensor), diff --git a/esphome/components/esp32_hall/esp32_hall.h b/esphome/components/esp32_hall/esp32_hall.h index 9727d45aa6..040280fff3 100644 --- a/esphome/components/esp32_hall/esp32_hall.h +++ b/esphome/components/esp32_hall/esp32_hall.h @@ -8,11 +8,8 @@ namespace esphome { namespace esp32_hall { -class ESP32HallSensor : public sensor::PollingSensorComponent { +class ESP32HallSensor : public sensor::Sensor, public PollingComponent { public: - explicit ESP32HallSensor(const std::string &name, uint32_t update_interval) - : sensor::PollingSensorComponent(name, update_interval) {} - void dump_config() override; void update() override; diff --git a/esphome/components/esp32_hall/sensor.py b/esphome/components/esp32_hall/sensor.py index 81a90c8c10..ec24f1aab6 100644 --- a/esphome/components/esp32_hall/sensor.py +++ b/esphome/components/esp32_hall/sensor.py @@ -1,21 +1,19 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor -from esphome.const import CONF_ID, CONF_NAME, CONF_UPDATE_INTERVAL, ESP_PLATFORM_ESP32, \ - UNIT_MICROTESLA, ICON_MAGNET +from esphome.const import CONF_ID, ESP_PLATFORM_ESP32, UNIT_MICROTESLA, ICON_MAGNET ESP_PLATFORMS = [ESP_PLATFORM_ESP32] esp32_hall_ns = cg.esphome_ns.namespace('esp32_hall') -ESP32HallSensor = esp32_hall_ns.class_('ESP32HallSensor', sensor.PollingSensorComponent) +ESP32HallSensor = esp32_hall_ns.class_('ESP32HallSensor', sensor.Sensor, cg.PollingComponent) CONFIG_SCHEMA = sensor.sensor_schema(UNIT_MICROTESLA, ICON_MAGNET, 1).extend({ cv.GenerateID(): cv.declare_id(ESP32HallSensor), - cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, -}).extend(cv.COMPONENT_SCHEMA) +}).extend(cv.polling_component_schema('60s')) def to_code(config): - var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME], config[CONF_UPDATE_INTERVAL]) + var = cg.new_Pvariable(config[CONF_ID]) yield cg.register_component(var, config) yield sensor.register_sensor(var, config) diff --git a/esphome/components/hx711/sensor.py b/esphome/components/hx711/sensor.py index bc22397065..2fc333a243 100644 --- a/esphome/components/hx711/sensor.py +++ b/esphome/components/hx711/sensor.py @@ -5,7 +5,7 @@ from esphome.components import sensor from esphome.const import CONF_CLK_PIN, CONF_GAIN, CONF_ID, ICON_SCALE hx711_ns = cg.esphome_ns.namespace('hx711') -HX711Sensor = hx711_ns.class_('HX711Sensor', sensor.PollingSensorComponent) +HX711Sensor = hx711_ns.class_('HX711Sensor', sensor.Sensor, cg.PollingComponent) CONF_DOUT_PIN = 'dout_pin' diff --git a/esphome/components/light/automation.py b/esphome/components/light/automation.py index 42a8319728..629073707e 100644 --- a/esphome/components/light/automation.py +++ b/esphome/components/light/automation.py @@ -128,7 +128,10 @@ def light_addressable_set_to_code(config, action_id, template_arg, args): if CONF_RANGE_TO in config: templ = yield cg.templatable(config[CONF_RANGE_TO], args, cg.int32) cg.add(var.set_range_to(templ)) - rgbw_to_exp = lambda x: int(round(x * 255)) + + def rgbw_to_exp(x): + return int(round(x * 255)) + if CONF_RED in config: templ = yield cg.templatable(config[CONF_RED], args, cg.uint8, to_exp=rgbw_to_exp) cg.add(var.set_red(templ)) diff --git a/esphome/components/max31855/sensor.py b/esphome/components/max31855/sensor.py index 7178488ebb..b4d9f82b03 100644 --- a/esphome/components/max31855/sensor.py +++ b/esphome/components/max31855/sensor.py @@ -4,7 +4,8 @@ from esphome.components import sensor, spi from esphome.const import CONF_ID, ICON_THERMOMETER, UNIT_CELSIUS max31855_ns = cg.esphome_ns.namespace('max31855') -MAX31855Sensor = max31855_ns.class_('MAX31855Sensor', sensor.PollingSensorComponent, spi.SPIDevice) +MAX31855Sensor = max31855_ns.class_('MAX31855Sensor', sensor.Sensor, cg.PollingComponent, + spi.SPIDevice) CONFIG_SCHEMA = sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({ cv.GenerateID(): cv.declare_id(MAX31855Sensor), diff --git a/esphome/components/max6675/sensor.py b/esphome/components/max6675/sensor.py index af089614f0..59d24a5283 100644 --- a/esphome/components/max6675/sensor.py +++ b/esphome/components/max6675/sensor.py @@ -4,7 +4,7 @@ from esphome.components import sensor, spi from esphome.const import CONF_ID, ICON_THERMOMETER, UNIT_CELSIUS max6675_ns = cg.esphome_ns.namespace('max6675') -MAX6675Sensor = max6675_ns.class_('MAX6675Sensor', sensor.PollingSensorComponent, +MAX6675Sensor = max6675_ns.class_('MAX6675Sensor', sensor.Sensor, cg.PollingComponent, spi.SPIDevice) CONFIG_SCHEMA = sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({ diff --git a/esphome/components/neopixelbus/neopixelbus_light.h b/esphome/components/neopixelbus/neopixelbus_light.h index 86ae21ddd0..68d99fb374 100644 --- a/esphome/components/neopixelbus/neopixelbus_light.h +++ b/esphome/components/neopixelbus/neopixelbus_light.h @@ -152,7 +152,7 @@ class NeoPixelRGBLightOutput : public NeoPixelBusLightOutputBasecontroller_->Pixels() + 3ULL * index; return light::ESPColorView(base + this->rgb_offsets_[0], base + this->rgb_offsets_[1], base + this->rgb_offsets_[2], nullptr, this->effect_data_ + index, &this->correction_); @@ -171,7 +171,7 @@ class NeoPixelRGBWLightOutput : public NeoPixelBusLightOutputBasecontroller_->Pixels() + 4ULL * index; return light::ESPColorView(base + this->rgb_offsets_[0], base + this->rgb_offsets_[1], base + this->rgb_offsets_[2], base + this->rgb_offsets_[3], this->effect_data_ + index, &this->correction_); diff --git a/esphome/components/partition/light_partition.h b/esphome/components/partition/light_partition.h index 398cbc6664..b68e3404f1 100644 --- a/esphome/components/partition/light_partition.h +++ b/esphome/components/partition/light_partition.h @@ -37,7 +37,23 @@ class PartitionLightOutput : public light::AddressableLight, public Component { auto &last_seg = this->segments_[this->segments_.size() - 1]; return last_seg.get_dst_offset() + last_seg.get_size(); } - light::ESPColorView operator[](int32_t index) const override { + void clear_effect_data() override { + for (auto &seg : this->segments_) { + seg.get_src()->clear_effect_data(); + } + } + light::LightTraits get_traits() override { return this->segments_[0].get_src()->get_traits(); } + void loop() override { + if (this->should_show_()) { + for (auto seg : this->segments_) { + seg.get_src()->schedule_show(); + } + this->mark_shown_(); + } + } + + protected: + light::ESPColorView get_view_internal(int32_t index) const override { uint32_t lo = 0; uint32_t hi = this->segments_.size() - 1; while (lo < hi) { @@ -61,22 +77,7 @@ class PartitionLightOutput : public light::AddressableLight, public Component { view.raw_set_color_correction(&this->correction_); return view; } - void clear_effect_data() override { - for (auto &seg : this->segments_) { - seg.get_src()->clear_effect_data(); - } - } - light::LightTraits get_traits() override { return this->segments_[0].get_src()->get_traits(); } - void loop() override { - if (this->should_show_()) { - for (auto seg : this->segments_) { - seg.get_src()->schedule_show(); - } - this->mark_shown_(); - } - } - protected: std::vector segments_; }; diff --git a/esphome/components/pulse_counter/sensor.py b/esphome/components/pulse_counter/sensor.py index 6fbdb00945..636147c138 100644 --- a/esphome/components/pulse_counter/sensor.py +++ b/esphome/components/pulse_counter/sensor.py @@ -18,7 +18,7 @@ COUNT_MODES = { COUNT_MODE_SCHEMA = cv.enum(COUNT_MODES, upper=True) PulseCounterSensor = pulse_counter_ns.class_('PulseCounterSensor', - sensor.PollingSensorComponent) + sensor.Sensor, cg.PollingComponent) def validate_internal_filter(value): diff --git a/esphome/components/pulse_width/sensor.py b/esphome/components/pulse_width/sensor.py index 42d1b0dbaa..0227adffce 100644 --- a/esphome/components/pulse_width/sensor.py +++ b/esphome/components/pulse_width/sensor.py @@ -6,7 +6,7 @@ from esphome.const import CONF_ID, CONF_PIN, UNIT_SECOND, ICON_TIMER pulse_width_ns = cg.esphome_ns.namespace('pulse_width') -PulseWidthSensor = pulse_width_ns.class_('PulseWidthSensor', sensor.PollingSensorComponent) +PulseWidthSensor = pulse_width_ns.class_('PulseWidthSensor', sensor.Sensor, cg.PollingComponent) CONFIG_SCHEMA = sensor.sensor_schema(UNIT_SECOND, ICON_TIMER, 3).extend({ cv.GenerateID(): cv.declare_id(PulseWidthSensor), diff --git a/esphome/components/template/sensor/__init__.py b/esphome/components/template/sensor/__init__.py index 1e9fe9cdee..788520877a 100644 --- a/esphome/components/template/sensor/__init__.py +++ b/esphome/components/template/sensor/__init__.py @@ -5,7 +5,7 @@ from esphome.components import sensor from esphome.const import CONF_ID, CONF_LAMBDA, CONF_STATE, UNIT_EMPTY, ICON_EMPTY from .. import template_ns -TemplateSensor = template_ns.class_('TemplateSensor', sensor.PollingSensorComponent) +TemplateSensor = template_ns.class_('TemplateSensor', sensor.Sensor, cg.PollingComponent) CONFIG_SCHEMA = sensor.sensor_schema(UNIT_EMPTY, ICON_EMPTY, 1).extend({ cv.GenerateID(): cv.declare_id(TemplateSensor), diff --git a/esphome/components/tsl2561/sensor.py b/esphome/components/tsl2561/sensor.py index 5171884a14..e2e333cc81 100644 --- a/esphome/components/tsl2561/sensor.py +++ b/esphome/components/tsl2561/sensor.py @@ -27,7 +27,8 @@ def validate_integration_time(value): return cv.enum(INTEGRATION_TIMES, int=True)(value) -TSL2561Sensor = tsl2561_ns.class_('TSL2561Sensor', sensor.PollingSensorComponent, i2c.I2CDevice) +TSL2561Sensor = tsl2561_ns.class_('TSL2561Sensor', sensor.Sensor, cg.PollingComponent, + i2c.I2CDevice) CONFIG_SCHEMA = sensor.sensor_schema(UNIT_LUX, ICON_BRIGHTNESS_5, 1).extend({ cv.GenerateID(): cv.declare_id(TSL2561Sensor), diff --git a/esphome/components/ultrasonic/sensor.py b/esphome/components/ultrasonic/sensor.py index fa3934853c..e4364f271c 100644 --- a/esphome/components/ultrasonic/sensor.py +++ b/esphome/components/ultrasonic/sensor.py @@ -9,7 +9,7 @@ CONF_PULSE_TIME = 'pulse_time' ultrasonic_ns = cg.esphome_ns.namespace('ultrasonic') UltrasonicSensorComponent = ultrasonic_ns.class_('UltrasonicSensorComponent', - sensor.PollingSensorComponent) + sensor.Sensor, cg.PollingComponent) CONFIG_SCHEMA = sensor.sensor_schema(UNIT_METER, ICON_ARROW_EXPAND_VERTICAL, 2).extend({ cv.GenerateID(): cv.declare_id(UltrasonicSensorComponent), diff --git a/esphome/components/uptime/sensor.py b/esphome/components/uptime/sensor.py index e4f78c6411..1dacc99653 100644 --- a/esphome/components/uptime/sensor.py +++ b/esphome/components/uptime/sensor.py @@ -4,7 +4,7 @@ from esphome.components import sensor from esphome.const import CONF_ID, UNIT_SECOND, ICON_TIMER uptime_ns = cg.esphome_ns.namespace('uptime') -UptimeSensor = uptime_ns.class_('UptimeSensor', sensor.PollingSensorComponent) +UptimeSensor = uptime_ns.class_('UptimeSensor', sensor.Sensor, cg.PollingComponent) CONFIG_SCHEMA = sensor.sensor_schema(UNIT_SECOND, ICON_TIMER, 0).extend({ cv.GenerateID(): cv.declare_id(UptimeSensor), diff --git a/esphome/components/wifi_signal/sensor.py b/esphome/components/wifi_signal/sensor.py index e53daede1f..1cc58009af 100644 --- a/esphome/components/wifi_signal/sensor.py +++ b/esphome/components/wifi_signal/sensor.py @@ -5,7 +5,7 @@ from esphome.const import CONF_ID, ICON_WIFI, UNIT_DECIBEL DEPENDENCIES = ['wifi'] wifi_signal_ns = cg.esphome_ns.namespace('wifi_signal') -WiFiSignalSensor = wifi_signal_ns.class_('WiFiSignalSensor', sensor.PollingSensorComponent) +WiFiSignalSensor = wifi_signal_ns.class_('WiFiSignalSensor', sensor.Sensor, cg.PollingComponent) CONFIG_SCHEMA = sensor.sensor_schema(UNIT_DECIBEL, ICON_WIFI, 0).extend({ cv.GenerateID(): cv.declare_id(WiFiSignalSensor), diff --git a/script/build_compile_commands.py b/script/build_compile_commands.py index 91eb75bd00..e6d761771f 100755 --- a/script/build_compile_commands.py +++ b/script/build_compile_commands.py @@ -7,6 +7,7 @@ import sys root_path = os.path.abspath(os.path.normpath(os.path.join(__file__, '..', '..'))) basepath = os.path.join(root_path, 'esphome') +temp_header_file = os.path.join(root_path, '.temp-clang-tidy.cpp') def walk_files(path): @@ -24,6 +25,24 @@ def shlex_quote(s): return u"'" + s.replace(u"'", u"'\"'\"'") + u"'" +def build_all_include(): + # Build a cpp file that includes all header files in this repo. + # Otherwise header-only integrations would not be tested by clang-tidy + headers = [] + for path in walk_files(basepath): + filetypes = ('.h',) + ext = os.path.splitext(path)[1] + if ext in filetypes: + path = os.path.relpath(path, root_path) + include_p = path.replace(os.path.sep, '/') + headers.append('#include "{}"'.format(include_p)) + headers.sort() + headers.append('') + content = '\n'.join(headers) + with codecs.open(temp_header_file, 'w', encoding='utf-8') as f: + f.write(content) + + def build_compile_commands(): gcc_flags_json = os.path.join(root_path, '.gcc-flags.json') if not os.path.isfile(gcc_flags_json): @@ -52,6 +71,7 @@ def build_compile_commands(): ext = os.path.splitext(path)[1] if ext in filetypes: source_files.append(os.path.abspath(path)) + source_files.append(temp_header_file) source_files.sort() compile_commands = [{ 'directory': root_path, @@ -71,6 +91,7 @@ def build_compile_commands(): def main(): + build_all_include() build_compile_commands() print("Done.") diff --git a/script/clang-tidy.py b/script/clang-tidy.py index 5b6129b35a..7187c16454 100755 --- a/script/clang-tidy.py +++ b/script/clang-tidy.py @@ -264,8 +264,6 @@ def main(): print('Ctrl-C detected, goodbye.') if tmpdir: shutil.rmtree(tmpdir) - if os.path.exists(temp_header_file): - os.remove(temp_header_file) os.kill(0, 9) if args.fix and failed_files: @@ -274,12 +272,8 @@ def main(): subprocess.call(['clang-apply-replacements-7', tmpdir]) except: print('Error applying fixes.\n', file=sys.stderr) - if os.path.exists(temp_header_file): - os.remove(temp_header_file) raise - if os.path.exists(temp_header_file): - os.remove(temp_header_file) sys.exit(return_code) From ce45c81069e6a3bd403327bc2af950bbb841e8a8 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Wed, 8 May 2019 10:35:07 +0200 Subject: [PATCH 08/17] Add longer MAX6675 delay --- esphome/components/max6675/max6675.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/max6675/max6675.cpp b/esphome/components/max6675/max6675.cpp index e9bbfb4a05..8ea7feb963 100644 --- a/esphome/components/max6675/max6675.cpp +++ b/esphome/components/max6675/max6675.cpp @@ -14,7 +14,7 @@ void MAX6675Sensor::update() { // Conversion time typ: 170ms, max: 220ms auto f = std::bind(&MAX6675Sensor::read_data_, this); - this->set_timeout("value", 220, f); + this->set_timeout("value", 250, f); } void MAX6675Sensor::setup() { From 53c182ad370a68e0bbbe24136c44b7dedb6f92ba Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Wed, 8 May 2019 10:37:13 +0200 Subject: [PATCH 09/17] Fix native API services not registered Fixes https://github.com/esphome/issues/issues/290 --- esphome/components/api/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index 97465f1f7c..b778257d66 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -67,6 +67,7 @@ def to_code(config): templ = cg.TemplateArguments(*template_args) trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], templ, conf[CONF_SERVICE], service_type_args) + cg.add(var.register_user_service(trigger)) yield automation.build_automation(trigger, func_args, conf) cg.add_define('USE_API') From bedf1b74831302bedde35a1a36412be3c5a930dc Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Wed, 8 May 2019 10:45:44 +0200 Subject: [PATCH 10/17] Fix fastled clockless not loading fastled base Ref https://github.com/esphome/issues/issues/268 --- esphome/components/fastled_clockless/light.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/fastled_clockless/light.py b/esphome/components/fastled_clockless/light.py index 340dc0ab05..30fa910e59 100644 --- a/esphome/components/fastled_clockless/light.py +++ b/esphome/components/fastled_clockless/light.py @@ -4,6 +4,8 @@ from esphome import pins from esphome.components import fastled_base from esphome.const import CONF_CHIPSET, CONF_NUM_LEDS, CONF_PIN, CONF_RGB_ORDER +AUTO_LOAD = ['fastled_base'] + CHIPSETS = [ 'NEOPIXEL', 'TM1829', From a07a835eb0f075a6166ec6c7629fd7c62985ffe8 Mon Sep 17 00:00:00 2001 From: Anders Persson Date: Wed, 8 May 2019 10:56:52 +0200 Subject: [PATCH 11/17] Custom tests (#529) * Add tests for custom components * Add more tests --- tests/test3.yaml | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/test3.yaml b/tests/test3.yaml index c6eab19440..3e61e78acf 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -122,6 +122,13 @@ sensor: name: Color Temperature integration_time: 700ms gain: 60x + - platform: custom + lambda: |- + auto s = new sensor::Sensor(); + return {s}; + sensors: + - id: custom_sensor + name: Custom Sensor time: - platform: homeassistant @@ -129,7 +136,7 @@ time: apds9960: address: 0x20 update_interval: 60s - + mpr121: id: mpr121_first address: 0x5A @@ -178,6 +185,13 @@ binary_sensor: - platform: ttp229_lsf channel: 1 name: TTP229 LSF Test + - platform: custom + lambda: |- + auto s = new binary_sensor::BinarySensor(); + return {s}; + sensors: + - id: custom_binary_sensor + name: Custom Binary Sensor remote_receiver: pin: GPIO12 @@ -233,6 +247,13 @@ switch: id: gpio_switch2 pin: GPIO1 interlock: *interlock + - platform: custom + lambda: |- + auto s = new switch::Switch(); + return {s}; + sensors: + - id: custom_switch + name: Custom Switch stepper: - platform: uln2003 From 968ff4b619ce17d75b740a1aecb508afd2eab201 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Wed, 8 May 2019 11:31:06 +0200 Subject: [PATCH 12/17] Fixes --- esphome/codegen.py | 2 +- esphome/components/ble_ibeacon/__init__.py | 18 --------- esphome/components/custom/sensor/__init__.py | 1 - esphome/components/custom/switch/__init__.py | 3 +- .../components/custom/text_sensor/__init__.py | 3 +- .../components/esp32_ble_tracker/__init__.py | 2 +- .../esp32_ble_tracker/esp32_ble_tracker.h | 5 +-- esphome/core_config.py | 2 +- script/lint-cpp | 2 +- tests/custom.h | 38 +++++++++++++++++++ tests/test3.yaml | 29 +++++++++++--- 11 files changed, 70 insertions(+), 35 deletions(-) delete mode 100644 esphome/components/ble_ibeacon/__init__.py create mode 100644 tests/custom.h diff --git a/esphome/codegen.py b/esphome/codegen.py index 883d5f8636..30f9ce6d2f 100644 --- a/esphome/codegen.py +++ b/esphome/codegen.py @@ -9,7 +9,7 @@ # pylint: disable=unused-import from esphome.cpp_generator import ( # noqa - Expression, RawExpression, TemplateArguments, + Expression, RawExpression, RawStatement, TemplateArguments, StructInitializer, ArrayInitializer, safe_exp, Statement, progmem_array, statement, variable, Pvariable, new_Pvariable, add, add_global, add_library, add_build_flag, add_define, diff --git a/esphome/components/ble_ibeacon/__init__.py b/esphome/components/ble_ibeacon/__init__.py deleted file mode 100644 index dac5b7c46f..0000000000 --- a/esphome/components/ble_ibeacon/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -import esphome.config_validation as cv -import esphome.codegen as cg -from esphome.components import esp32_ble_tracker -from esphome.const import CONF_ID - -DEPENDENCIES = ['esp32_ble_tracker'] -ble_ibeacon_ns = cg.esphome_ns.namespace('ble_ibeacon') -IBeaconListener = ble_ibeacon_ns.class_('IBeaconListener', esp32_ble_tracker.ESPBTDeviceListener) - - -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(IBeaconListener), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) - - -def to_code(config): - var = cg.new_Pvariable(config[CONF_ID]) - yield esp32_ble_tracker.register_ble_device(var, config) diff --git a/esphome/components/custom/sensor/__init__.py b/esphome/components/custom/sensor/__init__.py index 24dcdac997..726a65f9cb 100644 --- a/esphome/components/custom/sensor/__init__.py +++ b/esphome/components/custom/sensor/__init__.py @@ -21,5 +21,4 @@ def to_code(config): var = cg.variable(config[CONF_ID], rhs) for i, conf in enumerate(config[CONF_SENSORS]): sens = cg.Pvariable(conf[CONF_ID], var.get_sensor(i)) - cg.add(sens.set_name(conf[CONF_NAME])) yield sensor.register_sensor(sens, conf) diff --git a/esphome/components/custom/switch/__init__.py b/esphome/components/custom/switch/__init__.py index b0da14b4f1..6fcb5d6678 100644 --- a/esphome/components/custom/switch/__init__.py +++ b/esphome/components/custom/switch/__init__.py @@ -24,6 +24,5 @@ def to_code(config): rhs = CustomSwitchConstructor(template_) var = cg.variable(config[CONF_ID], rhs) for i, conf in enumerate(config[CONF_SWITCHES]): - switch_ = cg.new_Pvariable(conf[CONF_ID], var.get_switch(i)) - cg.add(switch_.set_name(conf[CONF_NAME])) + switch_ = cg.Pvariable(conf[CONF_ID], var.get_switch(i)) yield switch.register_switch(switch_, conf) diff --git a/esphome/components/custom/text_sensor/__init__.py b/esphome/components/custom/text_sensor/__init__.py index 40b8be8d76..42bcff04bb 100644 --- a/esphome/components/custom/text_sensor/__init__.py +++ b/esphome/components/custom/text_sensor/__init__.py @@ -24,6 +24,5 @@ def to_code(config): var = cg.variable(config[CONF_ID], rhs) for i, conf in enumerate(config[CONF_TEXT_SENSORS]): - text = cg.new_Pvariable(conf[CONF_ID], var.get_text_sensor(i)) - cg.add(text.set_name(conf[CONF_NAME])) + text = cg.Pvariable(conf[CONF_ID], var.get_text_sensor(i)) yield text_sensor.register_text_sensor(text, conf) diff --git a/esphome/components/esp32_ble_tracker/__init__.py b/esphome/components/esp32_ble_tracker/__init__.py index 05ca748a99..5a4862f733 100644 --- a/esphome/components/esp32_ble_tracker/__init__.py +++ b/esphome/components/esp32_ble_tracker/__init__.py @@ -4,7 +4,7 @@ from esphome.const import CONF_ID, CONF_SCAN_INTERVAL, ESP_PLATFORM_ESP32 from esphome.core import coroutine ESP_PLATFORMS = [ESP_PLATFORM_ESP32] -AUTO_LOAD = ['xiaomi_ble', 'ble_ibeacon'] +AUTO_LOAD = ['xiaomi_ble'] CONF_ESP32_BLE_ID = 'esp32_ble_id' esp32_ble_tracker_ns = cg.esphome_ns.namespace('esp32_ble_tracker') diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index a2c68063e7..f1bcada621 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -33,6 +33,7 @@ class ESPBTUUID { class ESPBLEiBeacon { public: + ESPBLEiBeacon() { memset(&this->beacon_data_, 0, sizeof(this->beacon_data_)); } ESPBLEiBeacon(const uint8_t *data); static optional from_manufacturer_data(const std::string &data); @@ -98,9 +99,7 @@ class ESPBTDeviceListener { public: virtual void on_scan_end() {} virtual bool parse_device(const ESPBTDevice &device) = 0; - void set_parent(ESP32BLETracker *parent) { - parent_ = parent; - } + void set_parent(ESP32BLETracker *parent) { parent_ = parent; } protected: ESP32BLETracker *parent_{nullptr}; diff --git a/esphome/core_config.py b/esphome/core_config.py index 9a636a28da..8d2f83c4f1 100644 --- a/esphome/core_config.py +++ b/esphome/core_config.py @@ -152,7 +152,7 @@ def add_includes(includes): for include in includes: path = CORE.relative_config_path(include) res = os.path.relpath(path, CORE.relative_build_path('src')).replace(os.path.sep, '/') - cg.add_global(cg.RawExpression(u'#include "{}"'.format(res))) + cg.add_global(cg.RawStatement(u'#include "{}"'.format(res))) @coroutine_with_priority(100.0) diff --git a/script/lint-cpp b/script/lint-cpp index c38351b606..b1766d8a28 100755 --- a/script/lint-cpp +++ b/script/lint-cpp @@ -12,5 +12,5 @@ fi set -x -script/clang-tidy.py -c --fix +script/clang-tidy.py -c --fix --all-headers script/clang-format.py -c -i diff --git a/tests/custom.h b/tests/custom.h new file mode 100644 index 0000000000..be1e91fb94 --- /dev/null +++ b/tests/custom.h @@ -0,0 +1,38 @@ + +class CustomSensor : public Component, public Sensor { + public: + void loop() override { + publish_state(42.0); + } +}; + +class CustomTextSensor : public Component, public TextSensor { + public: + void loop() override { + publish_state("Hello World"); + } +}; + +class CustomBinarySensor : public Component, public BinarySensor { + public: + void loop() override { + publish_state(false); + } +}; + +class CustomSwitch : public Switch { + protected: + void write_state(bool state) override { + ESP_LOGD("custom_switch", "Setting %s", ONOFF(state)); + } +}; + +class CustomComponent : public PollingComponent { + public: + void setup() override { + ESP_LOGD("custom_component", "Setup"); + } + void update() override { + ESP_LOGD("custom_component", "Update"); + } +}; diff --git a/tests/test3.yaml b/tests/test3.yaml index 3e61e78acf..2eedb25fc5 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -7,6 +7,8 @@ esphome: - wait_until: - api.connected - wifi.connected + includes: + - custom.h substitutions: devicename: test3 @@ -65,6 +67,7 @@ ota: logger: hardware_uart: UART1 level: DEBUG + esp8266_store_log_strings_in_flash: false web_server: @@ -124,7 +127,8 @@ sensor: gain: 60x - platform: custom lambda: |- - auto s = new sensor::Sensor(); + auto s = new CustomSensor(); + App.register_component(s); return {s}; sensors: - id: custom_sensor @@ -187,9 +191,10 @@ binary_sensor: name: TTP229 LSF Test - platform: custom lambda: |- - auto s = new binary_sensor::BinarySensor(); + auto s = new CustomBinarySensor(); + App.register_component(s); return {s}; - sensors: + binary_sensors: - id: custom_binary_sensor name: Custom Binary Sensor @@ -225,6 +230,14 @@ text_sensor: - platform: homeassistant entity_id: sensor.hello_world2 id: ha_hello_world2 + - platform: custom + lambda: |- + auto s = new CustomTextSensor(); + App.register_component(s); + return {s}; + text_sensors: + - id: custom_text_sensor + name: Custom Text Sensor script: - id: my_script @@ -249,12 +262,18 @@ switch: interlock: *interlock - platform: custom lambda: |- - auto s = new switch::Switch(); + auto s = new CustomSwitch(); return {s}; - sensors: + switches: - id: custom_switch name: Custom Switch +custom_component: + lambda: |- + auto s = new CustomComponent(); + s->set_update_interval(15000); + return {s}; + stepper: - platform: uln2003 id: my_stepper From 95428b4cfebb23876dc379d23ebdb98c7b145da8 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Wed, 8 May 2019 11:40:45 +0200 Subject: [PATCH 13/17] Lint --- esphome/components/custom/output/__init__.py | 4 ++-- esphome/components/custom/sensor/__init__.py | 2 +- esphome/components/custom/switch/__init__.py | 7 +++---- esphome/components/custom/text_sensor/__init__.py | 6 +++--- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/esphome/components/custom/output/__init__.py b/esphome/components/custom/output/__init__.py index 3266cbda98..cc4391d4ae 100644 --- a/esphome/components/custom/output/__init__.py +++ b/esphome/components/custom/output/__init__.py @@ -1,6 +1,6 @@ -from esphome.components import output -import esphome.config_validation as cv import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import output from esphome.const import CONF_ID, CONF_LAMBDA, CONF_OUTPUTS, CONF_TYPE from .. import custom_ns diff --git a/esphome/components/custom/sensor/__init__.py b/esphome/components/custom/sensor/__init__.py index 726a65f9cb..622d347d8a 100644 --- a/esphome/components/custom/sensor/__init__.py +++ b/esphome/components/custom/sensor/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor -from esphome.const import CONF_ID, CONF_LAMBDA, CONF_NAME, CONF_SENSORS +from esphome.const import CONF_ID, CONF_LAMBDA, CONF_SENSORS from .. import custom_ns CustomSensorConstructor = custom_ns.class_('CustomSensorConstructor') diff --git a/esphome/components/custom/switch/__init__.py b/esphome/components/custom/switch/__init__.py index 6fcb5d6678..dc5cb325bd 100644 --- a/esphome/components/custom/switch/__init__.py +++ b/esphome/components/custom/switch/__init__.py @@ -1,10 +1,9 @@ -from esphome.components import switch -import esphome.config_validation as cv import esphome.codegen as cg -from esphome.const import CONF_ID, CONF_LAMBDA, CONF_NAME, CONF_SWITCHES +import esphome.config_validation as cv +from esphome.components import switch +from esphome.const import CONF_ID, CONF_LAMBDA, CONF_SWITCHES from .. import custom_ns - CustomSwitchConstructor = custom_ns.class_('CustomSwitchConstructor') CONFIG_SCHEMA = cv.Schema({ diff --git a/esphome/components/custom/text_sensor/__init__.py b/esphome/components/custom/text_sensor/__init__.py index 42bcff04bb..38675da142 100644 --- a/esphome/components/custom/text_sensor/__init__.py +++ b/esphome/components/custom/text_sensor/__init__.py @@ -1,7 +1,7 @@ -from esphome.components import text_sensor -import esphome.config_validation as cv import esphome.codegen as cg -from esphome.const import CONF_ID, CONF_LAMBDA, CONF_NAME, CONF_TEXT_SENSORS +import esphome.config_validation as cv +from esphome.components import text_sensor +from esphome.const import CONF_ID, CONF_LAMBDA, CONF_TEXT_SENSORS from .. import custom_ns CustomTextSensorConstructor = custom_ns.class_('CustomTextSensorConstructor') From 3fe9c20188afa7d457d129f5faeb81cf69b6ba22 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Wed, 8 May 2019 14:56:54 +0200 Subject: [PATCH 14/17] Format --- esphome/components/adc/adc_sensor.h | 3 +-- esphome/components/ads1115/ads1115.cpp | 8 ++------ esphome/components/ads1115/ads1115.h | 3 +-- .../components/ble_presence/ble_presence_device.h | 4 +--- esphome/components/ble_rssi/ble_rssi_sensor.h | 4 +--- esphome/components/time/real_time_clock.h | 12 +++--------- esphome/components/xiaomi_miflora/xiaomi_miflora.h | 4 +--- esphome/components/xiaomi_mijia/xiaomi_mijia.h | 4 +--- 8 files changed, 11 insertions(+), 31 deletions(-) diff --git a/esphome/components/adc/adc_sensor.h b/esphome/components/adc/adc_sensor.h index e44d3ee8d7..7d26a67ae4 100644 --- a/esphome/components/adc/adc_sensor.h +++ b/esphome/components/adc/adc_sensor.h @@ -12,8 +12,7 @@ namespace adc { ADC_MODE(ADC_VCC) #endif -class ADCSensor : public sensor::Sensor, public PollingComponent, - public voltage_sampler::VoltageSampler { +class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage_sampler::VoltageSampler { public: #ifdef ARDUINO_ARCH_ESP32 /// Set the attenuation for this pin. Only available on the ESP32. diff --git a/esphome/components/ads1115/ads1115.cpp b/esphome/components/ads1115/ads1115.cpp index 924cd1e3e4..94ff3a1186 100644 --- a/esphome/components/ads1115/ads1115.cpp +++ b/esphome/components/ads1115/ads1115.cpp @@ -59,9 +59,7 @@ void ADS1115Component::setup() { } for (auto *sensor : this->sensors_) { this->set_interval(sensor->get_name(), sensor->update_interval(), - [this, sensor] { - this->request_measurement(sensor); - }); + [this, sensor] { this->request_measurement(sensor); }); } } void ADS1115Component::dump_config() { @@ -153,9 +151,7 @@ uint8_t ADS1115Sensor::get_multiplexer() const { return this->multiplexer_; } void ADS1115Sensor::set_multiplexer(ADS1115Multiplexer multiplexer) { this->multiplexer_ = multiplexer; } uint8_t ADS1115Sensor::get_gain() const { return this->gain_; } void ADS1115Sensor::set_gain(ADS1115Gain gain) { this->gain_ = gain; } -float ADS1115Sensor::sample() { - return this->parent_->request_measurement(this); -} +float ADS1115Sensor::sample() { return this->parent_->request_measurement(this); } void ADS1115Sensor::update() { float v = this->parent_->request_measurement(this); if (!isnan(v)) { diff --git a/esphome/components/ads1115/ads1115.h b/esphome/components/ads1115/ads1115.h index f9d00f9b19..966541ef4f 100644 --- a/esphome/components/ads1115/ads1115.h +++ b/esphome/components/ads1115/ads1115.h @@ -47,8 +47,7 @@ class ADS1115Component : public Component, public i2c::I2CDevice { }; /// Internal holder class that is in instance of Sensor so that the hub can create individual sensors. -class ADS1115Sensor : public sensor::Sensor, public PollingComponent, - public voltage_sampler::VoltageSampler { +class ADS1115Sensor : public sensor::Sensor, public PollingComponent, public voltage_sampler::VoltageSampler { public: ADS1115Sensor(ADS1115Component *parent) : parent_(parent) {} void update() override; diff --git a/esphome/components/ble_presence/ble_presence_device.h b/esphome/components/ble_presence/ble_presence_device.h index 04152d7695..262cc3eedf 100644 --- a/esphome/components/ble_presence/ble_presence_device.h +++ b/esphome/components/ble_presence/ble_presence_device.h @@ -13,9 +13,7 @@ class BLEPresenceDevice : public binary_sensor::BinarySensor, public esp32_ble_tracker::ESPBTDeviceListener, public Component { public: - void set_address(uint64_t address) { - address_ = address; - } + void set_address(uint64_t address) { address_ = address; } void on_scan_end() override { if (!this->found_) this->publish_state(false); diff --git a/esphome/components/ble_rssi/ble_rssi_sensor.h b/esphome/components/ble_rssi/ble_rssi_sensor.h index 633bf1e52f..2c296b3831 100644 --- a/esphome/components/ble_rssi/ble_rssi_sensor.h +++ b/esphome/components/ble_rssi/ble_rssi_sensor.h @@ -11,9 +11,7 @@ namespace ble_rssi { class BLERSSISensor : public sensor::Sensor, public esp32_ble_tracker::ESPBTDeviceListener, public Component { public: - void set_address(uint64_t address) { - address_ = address; - } + void set_address(uint64_t address) { address_ = address; } void on_scan_end() override { if (!this->found_) this->publish_state(NAN); diff --git a/esphome/components/time/real_time_clock.h b/esphome/components/time/real_time_clock.h index f416938717..b87636d20e 100644 --- a/esphome/components/time/real_time_clock.h +++ b/esphome/components/time/real_time_clock.h @@ -100,19 +100,13 @@ class RealTimeClock : public Component { std::string get_timezone() { return this->timezone_; } /// Get the time in the currently defined timezone. - ESPTime now() { - return ESPTime::from_epoch_utc(this->timestamp_now()); - } + ESPTime now() { return ESPTime::from_epoch_utc(this->timestamp_now()); } /// Get the time without any time zone or DST corrections. - ESPTime utcnow() { - return ESPTime::from_epoch_local(this->timestamp_now()); - } + ESPTime utcnow() { return ESPTime::from_epoch_local(this->timestamp_now()); } /// Get the current time as the UTC epoch since January 1st 1970. - time_t timestamp_now() { - return ::time(nullptr); - } + time_t timestamp_now() { return ::time(nullptr); } void call_setup() override; diff --git a/esphome/components/xiaomi_miflora/xiaomi_miflora.h b/esphome/components/xiaomi_miflora/xiaomi_miflora.h index 7a1459b3b9..d1f05cdcc7 100644 --- a/esphome/components/xiaomi_miflora/xiaomi_miflora.h +++ b/esphome/components/xiaomi_miflora/xiaomi_miflora.h @@ -12,9 +12,7 @@ namespace xiaomi_miflora { class XiaomiMiflora : public Component, public esp32_ble_tracker::ESPBTDeviceListener { public: - void set_address(uint64_t address) { - address_ = address; - } + void set_address(uint64_t address) { address_ = address; } bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override { if (device.address_uint64() != this->address_) diff --git a/esphome/components/xiaomi_mijia/xiaomi_mijia.h b/esphome/components/xiaomi_mijia/xiaomi_mijia.h index 6ed066f3be..814e33fa75 100644 --- a/esphome/components/xiaomi_mijia/xiaomi_mijia.h +++ b/esphome/components/xiaomi_mijia/xiaomi_mijia.h @@ -12,9 +12,7 @@ namespace xiaomi_mijia { class XiaomiMijia : public Component, public esp32_ble_tracker::ESPBTDeviceListener { public: - void set_address(uint64_t address) { - address_ = address; - } + void set_address(uint64_t address) { address_ = address; } bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override { if (device.address_uint64() != this->address_) From 3372ddc63d40571cde0f580af89058d437da004e Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Wed, 8 May 2019 15:26:44 +0200 Subject: [PATCH 15/17] Lint more filetypes --- esphome/components/ledc/output.py | 4 ++-- script/ci-custom.py | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/esphome/components/ledc/output.py b/esphome/components/ledc/output.py index fd75942672..63b32eedf0 100644 --- a/esphome/components/ledc/output.py +++ b/esphome/components/ledc/output.py @@ -10,8 +10,8 @@ ESP_PLATFORMS = [ESP_PLATFORM_ESP32] def validate_frequency_bit_depth(obj): - frequency = obj.get(CONF_FREQUENCY, 1000) - bit_depth = obj.get(CONF_BIT_DEPTH, 12) + frequency = obj[CONF_FREQUENCY] + bit_depth = obj[CONF_BIT_DEPTH] max_freq = APB_CLOCK_FREQ / (2**bit_depth) if frequency > max_freq: raise cv.Invalid('Maximum frequency for bit depth {} is {}Hz'.format(bit_depth, max_freq)) diff --git a/script/ci-custom.py b/script/ci-custom.py index ce69cd9455..7637f9313c 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -22,8 +22,18 @@ files = [] for root, _, fs in os.walk('esphome'): for f in fs: _, ext = os.path.splitext(f) - if ext in ('.h', '.c', '.cpp', '.tcc', '.py'): + if ext in ('.h', '.c', '.cpp', '.tcc', '.yaml', '.yml', '.ini', '.txt', + '.py', '.html', '.js', '.md'): files.append(os.path.join(root, f)) +ignore = [ + 'esphome/dashboard/static/materialize.min.js', + 'esphome/dashboard/static/ace.js', + 'esphome/dashboard/static/mode-yaml.js', + 'esphome/dashboard/static/theme-dreamweaver.js', + 'esphome/dashboard/static/jquery.validate.min.js', + 'esphome/dashboard/static/ext-searchbox.js', +] +files = [f for f in files if f not in ignore] files.sort() errors = collections.defaultdict(list) From f2506bb23bdab23a432e7eee855d385badeca143 Mon Sep 17 00:00:00 2001 From: gitolicious Date: Wed, 8 May 2019 15:37:18 +0200 Subject: [PATCH 16/17] Create .editorconfig (#524) * Create .editorconfig Code formatting instruction for editors https://editorconfig.org/ * Add tcc Co-authored-by: Otto Winter --- .editorconfig | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..f24d70487a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,27 @@ +root = true + +# general +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 + +# python +[*.{py}] +indent_style = space +indent_size = 4 + +# C++ +[*.{cpp,h,tcc}] +indent_style = space +indent_size = 2 + +# Web +[*.{js,html,css}] +indent_style = space +indent_size = 2 + +# YAML +[*.{yaml,yml}] +indent_style = space +indent_size = 2 From 86848b39db5bb2451718d1d6191490da843520cc Mon Sep 17 00:00:00 2001 From: gitolicious Date: Wed, 8 May 2019 15:39:22 +0200 Subject: [PATCH 17/17] Added save & validate button in editor window (#511) * Added save & validate button in editor window It felt a bit cumbersome to save&close the editor window, then click the validate button, see an error, locate your device from the list and open the editor again. Now it is possible to save&validate a configuration without leaving the editor. * Changed modal behavior to close one before the other * set data-node dynamically * show upload button on successful validation * Use disabled class * Update index.html * Fix mistake Co-authored-by: Otto Winter --- esphome/dashboard/static/esphome.js | 7 +++++++ esphome/dashboard/templates/index.html | 3 +++ 2 files changed, 10 insertions(+) diff --git a/esphome/dashboard/static/esphome.js b/esphome/dashboard/static/esphome.js index 9f7a23fdb8..5ec29ba0dd 100644 --- a/esphome/dashboard/static/esphome.js +++ b/esphome/dashboard/static/esphome.js @@ -430,6 +430,9 @@ const validateModal = new LogModalElem({ name: 'validate', onPrepare: (modalElem, config) => { modalElem.querySelector(".stop-logs").innerHTML = "Stop"; + modalElem.querySelector(".action-edit").setAttribute('data-node', validateModal.activeConfig); + modalElem.querySelector(".action-upload").setAttribute('data-node', validateModal.activeConfig); + modalElem.querySelector(".action-upload").classList.add('disabled'); }, onProcessExit: (modalElem, code) => { if (code === 0) { @@ -437,6 +440,7 @@ const validateModal = new LogModalElem({ html: `${validateModal.activeConfig} is valid 👍`, displayLength: 5000, }); + modalElem.querySelector(".action-upload").classList.remove('disabled'); } else { M.toast({ html: `${validateModal.activeConfig} is invalid 😕`, @@ -552,6 +556,7 @@ editor.session.setOption('useSoftTabs', true); editor.session.setOption('tabSize', 2); const saveButton = editModalElem.querySelector(".save-button"); +const saveValidateButton = editModalElem.querySelector(".save-validate-button"); const saveEditor = () => { fetch(`./edit?configuration=${activeEditorConfig}`, { credentials: "same-origin", @@ -572,12 +577,14 @@ editor.commands.addCommand({ }); saveButton.addEventListener('click', saveEditor); +saveValidateButton.addEventListener('click', saveEditor); document.querySelectorAll(".action-edit").forEach((btn) => { btn.addEventListener('click', (e) => { activeEditorConfig = e.target.getAttribute('data-node'); const modalInstance = M.Modal.getInstance(editModalElem); const filenameField = editModalElem.querySelector('.filename'); + editModalElem.querySelector(".save-validate-button").setAttribute('data-node', activeEditorConfig); filenameField.innerHTML = activeEditorConfig; fetch(`./edit?configuration=${activeEditorConfig}`, {credentials: "same-origin"}) diff --git a/esphome/dashboard/templates/index.html b/esphome/dashboard/templates/index.html index 82afee979d..e7259b719d 100644 --- a/esphome/dashboard/templates/index.html +++ b/esphome/dashboard/templates/index.html @@ -147,6 +147,8 @@

   
   
 
@@ -430,6 +432,7 @@