mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	
							
								
								
									
										27
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										6
									
								
								.gitpod.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.gitpod.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| ports: | ||||
| - port: 6052 | ||||
|   onOpen: open-preview | ||||
| tasks: | ||||
| - before: script/setup | ||||
|   command: python -m esphome config dashboard | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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"; } | ||||
|   | ||||
| @@ -3,19 +3,22 @@ | ||||
| #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 +27,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; | ||||
|   | ||||
| @@ -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])) | ||||
|  | ||||
|   | ||||
| @@ -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') | ||||
|   | ||||
| @@ -59,7 +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() { | ||||
| @@ -76,11 +76,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 +96,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 +107,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 +115,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<int16_t>(raw_conversion); | ||||
|  | ||||
| @@ -143,16 +143,22 @@ 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 | ||||
|   | ||||
| @@ -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,29 @@ 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<ADS1115Sensor *> 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 | ||||
|   | ||||
| @@ -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)) | ||||
|   | ||||
| @@ -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') | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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), | ||||
|   | ||||
| @@ -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)) | ||||
|   | ||||
| @@ -13,9 +13,7 @@ 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 +27,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; } | ||||
|  | ||||
|   | ||||
| @@ -11,9 +11,7 @@ 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 +25,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; } | ||||
|  | ||||
|   | ||||
| @@ -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)) | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -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') | ||||
| @@ -20,6 +20,5 @@ 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)) | ||||
|         cg.add(sens.set_name(conf[CONF_NAME])) | ||||
|         sens = cg.Pvariable(conf[CONF_ID], var.get_sensor(i)) | ||||
|         yield sensor.register_sensor(sens, conf) | ||||
|   | ||||
| @@ -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({ | ||||
| @@ -24,6 +23,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) | ||||
|   | ||||
| @@ -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') | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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), | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| 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'] | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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<uint8_t>(raw_data[i])); | ||||
|     } else { | ||||
|       sprintf(buf, "0x%02X ", static_cast<uint8_t>(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> 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<const uint8_t *>(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<const char *>(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 | ||||
|  | ||||
|   | ||||
| @@ -31,12 +31,32 @@ class ESPBTUUID { | ||||
|   esp_bt_uuid_t uuid_; | ||||
| }; | ||||
|  | ||||
| class ESPBLEiBeacon { | ||||
|  public: | ||||
|   ESPBLEiBeacon() { memset(&this->beacon_data_, 0, sizeof(this->beacon_data_)); } | ||||
|   ESPBLEiBeacon(const uint8_t *data); | ||||
|   static optional<ESPBLEiBeacon> 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 +71,13 @@ class ESPBTDevice { | ||||
|   const std::string &get_manufacturer_data() const; | ||||
|   const std::string &get_service_data() const; | ||||
|   const optional<ESPBTUUID> &get_service_data_uuid() const; | ||||
|   const optional<ESPBLEiBeacon> 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 +97,28 @@ 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); | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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', | ||||
|   | ||||
| @@ -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' | ||||
|  | ||||
|   | ||||
| @@ -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)) | ||||
|   | ||||
| @@ -112,7 +112,7 @@ template<typename... Ts> class AddressableSet : public Action<Ts...> { | ||||
|   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...)); | ||||
|   | ||||
| @@ -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,44 @@ 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)) | ||||
|  | ||||
|     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)) | ||||
|     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 | ||||
|   | ||||
| @@ -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') | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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), | ||||
|   | ||||
| @@ -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() { | ||||
|   | ||||
| @@ -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({ | ||||
|   | ||||
| @@ -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<int16_t *>(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; | ||||
|   | ||||
| @@ -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])) | ||||
|   | ||||
| @@ -152,7 +152,7 @@ class NeoPixelRGBLightOutput : public NeoPixelBusLightOutputBase<T_METHOD, T_COL | ||||
|   } | ||||
|  | ||||
|  protected: | ||||
|   light::ESPColorView get_view_internal(int32_t index) const override { | ||||
|   light::ESPColorView get_view_internal(int32_t index) const override {  // NOLINT | ||||
|     uint8_t *base = this->controller_->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 NeoPixelBusLightOutputBase<T_METHOD, T_CO | ||||
|   } | ||||
|  | ||||
|  protected: | ||||
|   light::ESPColorView get_view_internal(int32_t index) const override { | ||||
|   light::ESPColorView get_view_internal(int32_t index) const override {  // NOLINT | ||||
|     uint8_t *base = this->controller_->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_); | ||||
|   | ||||
| @@ -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<AddressableSegment> segments_; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -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): | ||||
|   | ||||
| @@ -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), | ||||
|   | ||||
| @@ -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', | ||||
|   | ||||
| @@ -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), | ||||
|   | ||||
| @@ -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), | ||||
|   | ||||
| @@ -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,13 @@ 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; | ||||
|  | ||||
|   | ||||
| @@ -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), | ||||
|   | ||||
| @@ -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), | ||||
|   | ||||
| @@ -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), | ||||
|   | ||||
							
								
								
									
										4
									
								
								esphome/components/voltage_sampler/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								esphome/components/voltage_sampler/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| import esphome.codegen as cg | ||||
|  | ||||
| voltage_sampler_ns = cg.esphome_ns.namespace('voltage_sampler') | ||||
| VoltageSampler = voltage_sampler_ns.class_('VoltageSampler') | ||||
							
								
								
									
										16
									
								
								esphome/components/voltage_sampler/voltage_sampler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								esphome/components/voltage_sampler/voltage_sampler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
| @@ -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++) { | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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(); | ||||
|   | ||||
| @@ -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), | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -22,11 +22,9 @@ bool parse_xiaomi_data_byte(uint8_t data_type, const uint8_t *data, uint8_t data | ||||
|  | ||||
| optional<XiaomiParseResult> 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 | ||||
|   | ||||
| @@ -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]) | ||||
|   | ||||
| @@ -12,8 +12,7 @@ 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_) | ||||
|   | ||||
| @@ -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]) | ||||
|   | ||||
| @@ -12,8 +12,7 @@ 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_) | ||||
|   | ||||
| @@ -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' | ||||
|   | ||||
| @@ -55,7 +55,7 @@ template<typename... Ts> 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: | ||||
|   | ||||
| @@ -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 { | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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: `<code class="inlinecode">${validateModal.activeConfig}</code> is valid 👍`, | ||||
|         displayLength: 5000, | ||||
|       }); | ||||
|       modalElem.querySelector(".action-upload").classList.remove('disabled'); | ||||
|     } else { | ||||
|       M.toast({ | ||||
|         html: `<code class="inlinecode">${validateModal.activeConfig}</code> 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"}) | ||||
|   | ||||
| @@ -147,6 +147,8 @@ | ||||
|     <pre class="log"></pre> | ||||
|   </div> | ||||
|   <div class="modal-footer"> | ||||
|     <a class="modal-close waves-effect waves-green btn-flat action-edit">Edit</a> | ||||
|     <a class="modal-close waves-effect waves-green btn-flat action-upload">Upload</a> | ||||
|     <a class="modal-close waves-effect waves-green btn-flat stop-logs">Stop</a> | ||||
|   </div> | ||||
| </div> | ||||
| @@ -430,6 +432,7 @@ | ||||
|   </div> | ||||
|   <div class="modal-footer"> | ||||
|     <a class="waves-effect waves-green btn-flat save-button">Save</a> | ||||
|     <a class="modal-close waves-effect waves-green btn-flat action-validate save-validate-button">Save & Validate</a> | ||||
|     <a class="modal-close waves-effect waves-green btn-flat">Close</a> | ||||
|   </div> | ||||
| </div> | ||||
|   | ||||
							
								
								
									
										100
									
								
								script/build_compile_commands.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										100
									
								
								script/build_compile_commands.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| #!/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') | ||||
| temp_header_file = os.path.join(root_path, '.temp-clang-tidy.cpp') | ||||
|  | ||||
|  | ||||
| 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_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): | ||||
|         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.append(temp_header_file) | ||||
|     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_all_include() | ||||
|     build_compile_commands() | ||||
|     print("Done.") | ||||
|  | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     main() | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 = [] | ||||
| @@ -265,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: | ||||
| @@ -275,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) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
							
								
								
									
										38
									
								
								tests/custom.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								tests/custom.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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"); | ||||
|   } | ||||
| }; | ||||
| @@ -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: | ||||
|  | ||||
| @@ -122,6 +125,14 @@ sensor: | ||||
|       name: Color Temperature | ||||
|     integration_time: 700ms | ||||
|     gain: 60x | ||||
|   - platform: custom | ||||
|     lambda: |- | ||||
|       auto s = new CustomSensor(); | ||||
|       App.register_component(s); | ||||
|       return {s}; | ||||
|     sensors: | ||||
|       - id: custom_sensor | ||||
|         name: Custom Sensor | ||||
|  | ||||
| time: | ||||
| - platform: homeassistant | ||||
| @@ -129,7 +140,7 @@ time: | ||||
| apds9960: | ||||
|   address: 0x20 | ||||
|   update_interval: 60s | ||||
|    | ||||
|  | ||||
| mpr121: | ||||
|   id: mpr121_first | ||||
|   address: 0x5A | ||||
| @@ -178,6 +189,14 @@ binary_sensor: | ||||
|   - platform: ttp229_lsf | ||||
|     channel: 1 | ||||
|     name: TTP229 LSF Test | ||||
|   - platform: custom | ||||
|     lambda: |- | ||||
|       auto s = new CustomBinarySensor(); | ||||
|       App.register_component(s); | ||||
|       return {s}; | ||||
|     binary_sensors: | ||||
|       - id: custom_binary_sensor | ||||
|         name: Custom Binary Sensor | ||||
|  | ||||
| remote_receiver: | ||||
|   pin: GPIO12 | ||||
| @@ -211,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 | ||||
| @@ -233,6 +260,19 @@ switch: | ||||
|     id: gpio_switch2 | ||||
|     pin: GPIO1 | ||||
|     interlock: *interlock | ||||
|   - platform: custom | ||||
|     lambda: |- | ||||
|       auto s = new CustomSwitch(); | ||||
|       return {s}; | ||||
|     switches: | ||||
|       - id: custom_switch | ||||
|         name: Custom Switch | ||||
|  | ||||
| custom_component: | ||||
|    lambda: |- | ||||
|      auto s = new CustomComponent(); | ||||
|      s->set_update_interval(15000); | ||||
|      return {s}; | ||||
|  | ||||
| stepper: | ||||
|   - platform: uln2003 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user