mirror of
https://github.com/esphome/esphome.git
synced 2024-12-02 03:34:18 +01:00
commit
5f66aac1b8
76 changed files with 576 additions and 220 deletions
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
|
# pylint: disable=unused-import
|
||||||
from esphome.cpp_generator import ( # noqa
|
from esphome.cpp_generator import ( # noqa
|
||||||
Expression, RawExpression, TemplateArguments,
|
Expression, RawExpression, RawStatement, TemplateArguments,
|
||||||
StructInitializer, ArrayInitializer, safe_exp, Statement,
|
StructInitializer, ArrayInitializer, safe_exp, Statement,
|
||||||
progmem_array, statement, variable, Pvariable, new_Pvariable,
|
progmem_array, statement, variable, Pvariable, new_Pvariable,
|
||||||
add, add_global, add_library, add_build_flag, add_define,
|
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; }
|
float ADCSensor::get_setup_priority() const { return setup_priority::DATA; }
|
||||||
void ADCSensor::update() {
|
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
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
float value_v = analogRead(this->pin_) / 4095.0f;
|
float value_v = analogRead(this->pin_) / 4095.0f;
|
||||||
switch (this->attenuation_) {
|
switch (this->attenuation_) {
|
||||||
|
@ -64,19 +69,16 @@ void ADCSensor::update() {
|
||||||
value_v *= 3.9;
|
value_v *= 3.9;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return value_v;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
#ifdef USE_ADC_SENSOR_VCC
|
#ifdef USE_ADC_SENSOR_VCC
|
||||||
float value_v = ESP.getVcc() / 1024.0f;
|
return ESP.getVcc() / 1024.0f;
|
||||||
#else
|
#else
|
||||||
float value_v = analogRead(this->pin_) / 1024.0f;
|
return analogRead(this->pin_) / 1024.0f;
|
||||||
#endif
|
#endif
|
||||||
#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
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
std::string ADCSensor::unique_id() { return get_mac_address() + "-adc"; }
|
std::string ADCSensor::unique_id() { return get_mac_address() + "-adc"; }
|
||||||
|
|
|
@ -3,19 +3,22 @@
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/core/esphal.h"
|
#include "esphome/core/esphal.h"
|
||||||
#include "esphome/components/sensor/sensor.h"
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
#include "esphome/components/voltage_sampler/voltage_sampler.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace adc {
|
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:
|
public:
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
/// Set the attenuation for this pin. Only available on the ESP32.
|
/// Set the attenuation for this pin. Only available on the ESP32.
|
||||||
void set_attenuation(adc_attenuation_t attenuation);
|
void set_attenuation(adc_attenuation_t attenuation);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ========== INTERNAL METHODS ==========
|
|
||||||
// (In most use cases you won't need these)
|
|
||||||
/// Update adc values.
|
/// Update adc values.
|
||||||
void update() override;
|
void update() override;
|
||||||
/// Setup ADc
|
/// Setup ADc
|
||||||
|
@ -24,6 +27,7 @@ class ADCSensor : public sensor::Sensor, public PollingComponent {
|
||||||
/// `HARDWARE_LATE` setup priority.
|
/// `HARDWARE_LATE` setup priority.
|
||||||
float get_setup_priority() const override;
|
float get_setup_priority() const override;
|
||||||
void set_pin(uint8_t pin) { this->pin_ = pin; }
|
void set_pin(uint8_t pin) { this->pin_ = pin; }
|
||||||
|
float sample() override;
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
std::string unique_id() override;
|
std::string unique_id() override;
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome import pins
|
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
|
from esphome.const import CONF_ATTENUATION, CONF_ID, CONF_PIN, ICON_FLASH, UNIT_VOLT
|
||||||
|
|
||||||
|
|
||||||
|
AUTO_LOAD = ['voltage_sampler']
|
||||||
|
|
||||||
ATTENUATION_MODES = {
|
ATTENUATION_MODES = {
|
||||||
'0db': cg.global_ns.ADC_0db,
|
'0db': cg.global_ns.ADC_0db,
|
||||||
'2.5db': cg.global_ns.ADC_2_5db,
|
'2.5db': cg.global_ns.ADC_2_5db,
|
||||||
|
@ -20,7 +23,8 @@ def validate_adc_pin(value):
|
||||||
|
|
||||||
|
|
||||||
adc_ns = cg.esphome_ns.namespace('adc')
|
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({
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 2).extend({
|
||||||
cv.GenerateID(): cv.declare_id(ADCSensor),
|
cv.GenerateID(): cv.declare_id(ADCSensor),
|
||||||
|
@ -37,7 +41,6 @@ def to_code(config):
|
||||||
|
|
||||||
if config[CONF_PIN] == 'VCC':
|
if config[CONF_PIN] == 'VCC':
|
||||||
cg.add_define('USE_ADC_SENSOR_VCC')
|
cg.add_define('USE_ADC_SENSOR_VCC')
|
||||||
cg.add_global(cg.global_ns.ADC_MODE(cg.global_ns.ADC_VCC))
|
|
||||||
else:
|
else:
|
||||||
cg.add(var.set_pin(config[CONF_PIN]))
|
cg.add(var.set_pin(config[CONF_PIN]))
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ from esphome.components import i2c
|
||||||
from esphome.const import CONF_ID
|
from esphome.const import CONF_ID
|
||||||
|
|
||||||
DEPENDENCIES = ['i2c']
|
DEPENDENCIES = ['i2c']
|
||||||
AUTO_LOAD = ['sensor']
|
AUTO_LOAD = ['sensor', 'voltage_sampler']
|
||||||
MULTI_CONF = True
|
MULTI_CONF = True
|
||||||
|
|
||||||
ads1115_ns = cg.esphome_ns.namespace('ads1115')
|
ads1115_ns = cg.esphome_ns.namespace('ads1115')
|
||||||
|
|
|
@ -59,7 +59,7 @@ void ADS1115Component::setup() {
|
||||||
}
|
}
|
||||||
for (auto *sensor : this->sensors_) {
|
for (auto *sensor : this->sensors_) {
|
||||||
this->set_interval(sensor->get_name(), sensor->update_interval(),
|
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() {
|
void ADS1115Component::dump_config() {
|
||||||
|
@ -76,11 +76,11 @@ void ADS1115Component::dump_config() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float ADS1115Component::get_setup_priority() const { return setup_priority::DATA; }
|
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;
|
uint16_t config;
|
||||||
if (!this->read_byte_16(ADS1115_REGISTER_CONFIG, &config)) {
|
if (!this->read_byte_16(ADS1115_REGISTER_CONFIG, &config)) {
|
||||||
this->status_set_warning();
|
this->status_set_warning();
|
||||||
return;
|
return NAN;
|
||||||
}
|
}
|
||||||
// Multiplexer
|
// Multiplexer
|
||||||
// 0bxBBBxxxxxxxxxxxx
|
// 0bxBBBxxxxxxxxxxxx
|
||||||
|
@ -96,7 +96,7 @@ void ADS1115Component::request_measurement_(ADS1115Sensor *sensor) {
|
||||||
|
|
||||||
if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) {
|
if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) {
|
||||||
this->status_set_warning();
|
this->status_set_warning();
|
||||||
return;
|
return NAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// about 1.6 ms with 860 samples per second
|
// about 1.6 ms with 860 samples per second
|
||||||
|
@ -107,7 +107,7 @@ void ADS1115Component::request_measurement_(ADS1115Sensor *sensor) {
|
||||||
if (millis() - start > 100) {
|
if (millis() - start > 100) {
|
||||||
ESP_LOGW(TAG, "Reading ADS1115 timed out");
|
ESP_LOGW(TAG, "Reading ADS1115 timed out");
|
||||||
this->status_set_warning();
|
this->status_set_warning();
|
||||||
return;
|
return NAN;
|
||||||
}
|
}
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ void ADS1115Component::request_measurement_(ADS1115Sensor *sensor) {
|
||||||
uint16_t raw_conversion;
|
uint16_t raw_conversion;
|
||||||
if (!this->read_byte_16(ADS1115_REGISTER_CONVERSION, &raw_conversion)) {
|
if (!this->read_byte_16(ADS1115_REGISTER_CONVERSION, &raw_conversion)) {
|
||||||
this->status_set_warning();
|
this->status_set_warning();
|
||||||
return;
|
return NAN;
|
||||||
}
|
}
|
||||||
auto signed_conversion = static_cast<int16_t>(raw_conversion);
|
auto signed_conversion = static_cast<int16_t>(raw_conversion);
|
||||||
|
|
||||||
|
@ -143,16 +143,22 @@ void ADS1115Component::request_measurement_(ADS1115Sensor *sensor) {
|
||||||
millivolts = NAN;
|
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();
|
this->status_clear_warning();
|
||||||
|
return millivolts / 1e4f;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ADS1115Sensor::get_multiplexer() const { return this->multiplexer_; }
|
uint8_t ADS1115Sensor::get_multiplexer() const { return this->multiplexer_; }
|
||||||
void ADS1115Sensor::set_multiplexer(ADS1115Multiplexer multiplexer) { this->multiplexer_ = multiplexer; }
|
void ADS1115Sensor::set_multiplexer(ADS1115Multiplexer multiplexer) { this->multiplexer_ = multiplexer; }
|
||||||
uint8_t ADS1115Sensor::get_gain() const { return this->gain_; }
|
uint8_t ADS1115Sensor::get_gain() const { return this->gain_; }
|
||||||
void ADS1115Sensor::set_gain(ADS1115Gain gain) { this->gain_ = 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 ads1115
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/components/sensor/sensor.h"
|
#include "esphome/components/sensor/sensor.h"
|
||||||
#include "esphome/components/i2c/i2c.h"
|
#include "esphome/components/i2c/i2c.h"
|
||||||
|
#include "esphome/components/voltage_sampler/voltage_sampler.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ads1115 {
|
namespace ads1115 {
|
||||||
|
@ -38,28 +39,29 @@ class ADS1115Component : public Component, public i2c::I2CDevice {
|
||||||
/// HARDWARE_LATE setup priority
|
/// HARDWARE_LATE setup priority
|
||||||
float get_setup_priority() const override;
|
float get_setup_priority() const override;
|
||||||
|
|
||||||
protected:
|
|
||||||
/// Helper method to request a measurement from a sensor.
|
/// Helper method to request a measurement from a sensor.
|
||||||
void request_measurement_(ADS1115Sensor *sensor);
|
float request_measurement(ADS1115Sensor *sensor);
|
||||||
|
|
||||||
|
protected:
|
||||||
std::vector<ADS1115Sensor *> sensors_;
|
std::vector<ADS1115Sensor *> sensors_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Internal holder class that is in instance of Sensor so that the hub can create individual 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:
|
public:
|
||||||
|
ADS1115Sensor(ADS1115Component *parent) : parent_(parent) {}
|
||||||
|
void update() override;
|
||||||
void set_multiplexer(ADS1115Multiplexer multiplexer);
|
void set_multiplexer(ADS1115Multiplexer multiplexer);
|
||||||
void set_gain(ADS1115Gain gain);
|
void set_gain(ADS1115Gain gain);
|
||||||
|
|
||||||
// ========== INTERNAL METHODS ==========
|
float sample() override;
|
||||||
// (In most use cases you won't need these)
|
|
||||||
uint8_t get_multiplexer() const;
|
uint8_t get_multiplexer() const;
|
||||||
uint8_t get_gain() const;
|
uint8_t get_gain() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
ADS1115Component *parent_;
|
||||||
ADS1115Multiplexer multiplexer_;
|
ADS1115Multiplexer multiplexer_;
|
||||||
ADS1115Gain gain_;
|
ADS1115Gain gain_;
|
||||||
uint32_t update_interval_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ads1115
|
} // namespace ads1115
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
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.components.ads1115 import ADS1115Component
|
||||||
from esphome.const import CONF_GAIN, CONF_MULTIPLEXER, ICON_FLASH, UNIT_VOLT, CONF_ID
|
from esphome.const import CONF_GAIN, CONF_MULTIPLEXER, ICON_FLASH, UNIT_VOLT, CONF_ID
|
||||||
from esphome.py_compat import string_types
|
from esphome.py_compat import string_types
|
||||||
|
@ -40,7 +40,8 @@ def validate_gain(value):
|
||||||
return cv.enum(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'
|
CONF_ADS1115_ID = 'ads1115_id'
|
||||||
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 3).extend({
|
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):
|
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 sensor.register_sensor(var, config)
|
||||||
|
yield cg.register_component(var, config)
|
||||||
|
|
||||||
cg.add(var.set_multiplexer(config[CONF_MULTIPLEXER]))
|
cg.add(var.set_multiplexer(config[CONF_MULTIPLEXER]))
|
||||||
cg.add(var.set_gain(config[CONF_GAIN]))
|
cg.add(var.set_gain(config[CONF_GAIN]))
|
||||||
|
|
||||||
hub = yield cg.get_variable(config[CONF_ADS1115_ID])
|
cg.add(paren.register_sensor(var))
|
||||||
cg.add(hub.register_sensor(var))
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ def to_code(config):
|
||||||
templ = cg.TemplateArguments(*template_args)
|
templ = cg.TemplateArguments(*template_args)
|
||||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], templ,
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], templ,
|
||||||
conf[CONF_SERVICE], service_type_args)
|
conf[CONF_SERVICE], service_type_args)
|
||||||
|
cg.add(var.register_user_service(trigger))
|
||||||
yield automation.build_automation(trigger, func_args, conf)
|
yield automation.build_automation(trigger, func_args, conf)
|
||||||
|
|
||||||
cg.add_define('USE_API')
|
cg.add_define('USE_API')
|
||||||
|
|
|
@ -260,7 +260,6 @@ APIConnection::APIConnection(AsyncClient *client, APIServer *parent)
|
||||||
}
|
}
|
||||||
APIConnection::~APIConnection() { delete this->client_; }
|
APIConnection::~APIConnection() { delete this->client_; }
|
||||||
void APIConnection::on_error_(int8_t error) {
|
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
|
// disconnect will also be called, nothing to do here
|
||||||
this->remove_ = true;
|
this->remove_ = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ BH1750_RESOLUTIONS = {
|
||||||
0.5: BH1750Resolution.BH1750_RESOLUTION_0P5_LX,
|
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({
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_LUX, ICON_BRIGHTNESS_5, 1).extend({
|
||||||
cv.GenerateID(): cv.declare_id(BH1750Sensor),
|
cv.GenerateID(): cv.declare_id(BH1750Sensor),
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components import binary_sensor
|
from esphome.components import binary_sensor, esp32_ble_tracker
|
||||||
from esphome.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESP_BLE_DEVICE_SCHEMA, \
|
from esphome.const import CONF_MAC_ADDRESS, CONF_ID
|
||||||
ESPBTDeviceListener
|
|
||||||
from esphome.const import CONF_MAC_ADDRESS, CONF_NAME, CONF_ID
|
|
||||||
|
|
||||||
DEPENDENCIES = ['esp32_ble_tracker']
|
DEPENDENCIES = ['esp32_ble_tracker']
|
||||||
|
|
||||||
ble_presence_ns = cg.esphome_ns.namespace('ble_presence')
|
ble_presence_ns = cg.esphome_ns.namespace('ble_presence')
|
||||||
BLEPresenceDevice = ble_presence_ns.class_('BLEPresenceDevice', binary_sensor.BinarySensor,
|
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({
|
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({
|
||||||
cv.GenerateID(): cv.declare_id(BLEPresenceDevice),
|
cv.GenerateID(): cv.declare_id(BLEPresenceDevice),
|
||||||
cv.Required(CONF_MAC_ADDRESS): cv.mac_address,
|
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):
|
def to_code(config):
|
||||||
hub = yield cg.get_variable(config[CONF_ESP32_BLE_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME], hub, config[CONF_MAC_ADDRESS].as_hex)
|
|
||||||
yield cg.register_component(var, config)
|
yield cg.register_component(var, config)
|
||||||
|
yield esp32_ble_tracker.register_ble_device(var, config)
|
||||||
yield binary_sensor.register_binary_sensor(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 esp32_ble_tracker::ESPBTDeviceListener,
|
||||||
public Component {
|
public Component {
|
||||||
public:
|
public:
|
||||||
BLEPresenceDevice(const std::string &name, esp32_ble_tracker::ESP32BLETracker *parent, uint64_t address)
|
void set_address(uint64_t address) { address_ = address; }
|
||||||
: binary_sensor::BinarySensor(name), esp32_ble_tracker::ESPBTDeviceListener(parent), address_(address) {}
|
|
||||||
|
|
||||||
void on_scan_end() override {
|
void on_scan_end() override {
|
||||||
if (!this->found_)
|
if (!this->found_)
|
||||||
this->publish_state(false);
|
this->publish_state(false);
|
||||||
|
@ -29,7 +27,6 @@ class BLEPresenceDevice : public binary_sensor::BinarySensor,
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void setup() override { this->setup_ble(); }
|
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
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 {
|
class BLERSSISensor : public sensor::Sensor, public esp32_ble_tracker::ESPBTDeviceListener, public Component {
|
||||||
public:
|
public:
|
||||||
BLERSSISensor(const std::string &name, esp32_ble_tracker::ESP32BLETracker *parent, uint64_t address)
|
void set_address(uint64_t address) { address_ = address; }
|
||||||
: sensor::Sensor(name), esp32_ble_tracker::ESPBTDeviceListener(parent), address_(address) {}
|
|
||||||
|
|
||||||
void on_scan_end() override {
|
void on_scan_end() override {
|
||||||
if (!this->found_)
|
if (!this->found_)
|
||||||
this->publish_state(NAN);
|
this->publish_state(NAN);
|
||||||
|
@ -27,7 +25,6 @@ class BLERSSISensor : public sensor::Sensor, public esp32_ble_tracker::ESPBTDevi
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void setup() override { this->setup_ble(); }
|
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components import sensor
|
from esphome.components import sensor, esp32_ble_tracker
|
||||||
from esphome.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESPBTDeviceListener, \
|
from esphome.const import CONF_MAC_ADDRESS, CONF_ID, UNIT_DECIBEL, ICON_SIGNAL
|
||||||
ESP_BLE_DEVICE_SCHEMA
|
|
||||||
from esphome.const import CONF_MAC_ADDRESS, CONF_NAME, CONF_ID, UNIT_DECIBEL, ICON_SIGNAL
|
|
||||||
|
|
||||||
DEPENDENCIES = ['esp32_ble_tracker']
|
DEPENDENCIES = ['esp32_ble_tracker']
|
||||||
|
|
||||||
ble_rssi_ns = cg.esphome_ns.namespace('ble_rssi')
|
ble_rssi_ns = cg.esphome_ns.namespace('ble_rssi')
|
||||||
BLERSSISensor = ble_rssi_ns.class_('BLERSSISensor', sensor.Sensor, cg.Component,
|
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({
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_DECIBEL, ICON_SIGNAL, 0).extend({
|
||||||
cv.GenerateID(): cv.declare_id(BLERSSISensor),
|
cv.GenerateID(): cv.declare_id(BLERSSISensor),
|
||||||
cv.Required(CONF_MAC_ADDRESS): cv.mac_address,
|
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):
|
def to_code(config):
|
||||||
hub = yield cg.get_variable(config[CONF_ESP32_BLE_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME], hub, config[CONF_MAC_ADDRESS].as_hex)
|
|
||||||
yield cg.register_component(var, config)
|
yield cg.register_component(var, config)
|
||||||
|
yield esp32_ble_tracker.register_ble_device(var, config)
|
||||||
yield sensor.register_sensor(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.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 esphome.const import CONF_ID, CONF_LAMBDA, CONF_OUTPUTS, CONF_TYPE
|
||||||
from .. import custom_ns
|
from .. import custom_ns
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components import sensor
|
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
|
from .. import custom_ns
|
||||||
|
|
||||||
CustomSensorConstructor = custom_ns.class_('CustomSensorConstructor')
|
CustomSensorConstructor = custom_ns.class_('CustomSensorConstructor')
|
||||||
|
@ -20,6 +20,5 @@ def to_code(config):
|
||||||
rhs = CustomSensorConstructor(template_)
|
rhs = CustomSensorConstructor(template_)
|
||||||
var = cg.variable(config[CONF_ID], rhs)
|
var = cg.variable(config[CONF_ID], rhs)
|
||||||
for i, conf in enumerate(config[CONF_SENSORS]):
|
for i, conf in enumerate(config[CONF_SENSORS]):
|
||||||
sens = cg.new_Pvariable(conf[CONF_ID], var.get_switch(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)
|
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
|
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
|
from .. import custom_ns
|
||||||
|
|
||||||
|
|
||||||
CustomSwitchConstructor = custom_ns.class_('CustomSwitchConstructor')
|
CustomSwitchConstructor = custom_ns.class_('CustomSwitchConstructor')
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.Schema({
|
CONFIG_SCHEMA = cv.Schema({
|
||||||
|
@ -24,6 +23,5 @@ def to_code(config):
|
||||||
rhs = CustomSwitchConstructor(template_)
|
rhs = CustomSwitchConstructor(template_)
|
||||||
var = cg.variable(config[CONF_ID], rhs)
|
var = cg.variable(config[CONF_ID], rhs)
|
||||||
for i, conf in enumerate(config[CONF_SWITCHES]):
|
for i, conf in enumerate(config[CONF_SWITCHES]):
|
||||||
switch_ = cg.new_Pvariable(conf[CONF_ID], var.get_switch(i))
|
switch_ = cg.Pvariable(conf[CONF_ID], var.get_switch(i))
|
||||||
cg.add(switch_.set_name(conf[CONF_NAME]))
|
|
||||||
yield switch.register_switch(switch_, conf)
|
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
|
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
|
from .. import custom_ns
|
||||||
|
|
||||||
CustomTextSensorConstructor = custom_ns.class_('CustomTextSensorConstructor')
|
CustomTextSensorConstructor = custom_ns.class_('CustomTextSensorConstructor')
|
||||||
|
@ -24,6 +24,5 @@ def to_code(config):
|
||||||
var = cg.variable(config[CONF_ID], rhs)
|
var = cg.variable(config[CONF_ID], rhs)
|
||||||
|
|
||||||
for i, conf in enumerate(config[CONF_TEXT_SENSORS]):
|
for i, conf in enumerate(config[CONF_TEXT_SENSORS]):
|
||||||
text = cg.new_Pvariable(conf[CONF_ID], var.get_text_sensor(i))
|
text = cg.Pvariable(conf[CONF_ID], var.get_text_sensor(i))
|
||||||
cg.add(text.set_name(conf[CONF_NAME]))
|
|
||||||
yield text_sensor.register_text_sensor(text, conf)
|
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
|
from esphome.const import CONF_ID, CONF_PIN, UNIT_PERCENT, ICON_PERCENT
|
||||||
|
|
||||||
duty_cycle_ns = cg.esphome_ns.namespace('duty_cycle')
|
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({
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_PERCENT, ICON_PERCENT, 1).extend({
|
||||||
cv.GenerateID(): cv.declare_id(DutyCycleSensor),
|
cv.GenerateID(): cv.declare_id(DutyCycleSensor),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import CONF_ID, CONF_SCAN_INTERVAL, ESP_PLATFORM_ESP32
|
from esphome.const import CONF_ID, CONF_SCAN_INTERVAL, ESP_PLATFORM_ESP32
|
||||||
|
from esphome.core import coroutine
|
||||||
|
|
||||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||||
AUTO_LOAD = ['xiaomi_ble']
|
AUTO_LOAD = ['xiaomi_ble']
|
||||||
|
@ -24,3 +25,10 @@ def to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
yield cg.register_component(var, config)
|
yield cg.register_component(var, config)
|
||||||
cg.add(var.set_scan_interval(config[CONF_SCAN_INTERVAL]))
|
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() : uuid_() {}
|
||||||
ESPBTUUID ESPBTUUID::from_uint16(uint16_t uuid) {
|
ESPBTUUID ESPBTUUID::from_uint16(uint16_t uuid) {
|
||||||
ESPBTUUID ret;
|
ESPBTUUID ret;
|
||||||
|
@ -259,12 +275,22 @@ std::string ESPBTUUID::to_string() {
|
||||||
return sbuf;
|
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) {
|
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++)
|
for (uint8_t i = 0; i < ESP_BD_ADDR_LEN; i++)
|
||||||
this->address_[i] = param.bda[i];
|
this->address_[i] = param.bda[i];
|
||||||
this->address_type_ = param.ble_addr_type;
|
this->address_type_ = param.ble_addr_type;
|
||||||
this->rssi_ = param.rssi;
|
this->rssi_ = param.rssi;
|
||||||
this->parse_adv(param);
|
this->parse_adv_(param);
|
||||||
|
|
||||||
#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
|
#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
|
||||||
ESP_LOGVV(TAG, "Parse Result:");
|
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);
|
this->address_[2], this->address_[3], this->address_[4], this->address_[5], address_type);
|
||||||
|
|
||||||
ESP_LOGVV(TAG, " RSSI: %d", this->rssi_);
|
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()) {
|
if (this->tx_power_.has_value()) {
|
||||||
ESP_LOGVV(TAG, " TX Power: %d", *this->tx_power_);
|
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_) {
|
for (auto uuid : this->service_uuids_) {
|
||||||
ESP_LOGVV(TAG, " Service UUID: %s", uuid.to_string().c_str());
|
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, " Manufacturer data: %s", hexencode(this->manufacturer_data_).c_str());
|
||||||
ESP_LOGVV(TAG, " Service data: '%s'", this->service_data_.c_str());
|
ESP_LOGVV(TAG, " Service data: %s", hexencode(this->service_data_).c_str());
|
||||||
|
|
||||||
if (this->service_data_uuid_.has_value()) {
|
if (this->service_data_uuid_.has_value()) {
|
||||||
ESP_LOGVV(TAG, " Service Data UUID: %s", this->service_data_uuid_->to_string().c_str());
|
ESP_LOGVV(TAG, " Service Data UUID: %s", this->service_data_uuid_->to_string().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
char buffer[200];
|
ESP_LOGVV(TAG, "Adv data: %s",
|
||||||
size_t off = 0;
|
hexencode(std::string(reinterpret_cast<const char *>(param.ble_adv), param.adv_data_len)).c_str());
|
||||||
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);
|
|
||||||
#endif
|
#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;
|
size_t offset = 0;
|
||||||
const uint8_t *payload = param.ble_adv;
|
const uint8_t *payload = param.ble_adv;
|
||||||
uint8_t len = param.adv_data_len;
|
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 esp32_ble_tracker
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
|
|
|
@ -31,12 +31,32 @@ class ESPBTUUID {
|
||||||
esp_bt_uuid_t uuid_;
|
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 {
|
class ESPBTDevice {
|
||||||
public:
|
public:
|
||||||
void parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param ¶m);
|
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;
|
std::string address_str() const;
|
||||||
|
|
||||||
uint64_t address_uint64() const;
|
uint64_t address_uint64() const;
|
||||||
|
@ -51,8 +71,13 @@ class ESPBTDevice {
|
||||||
const std::string &get_manufacturer_data() const;
|
const std::string &get_manufacturer_data() const;
|
||||||
const std::string &get_service_data() const;
|
const std::string &get_service_data() const;
|
||||||
const optional<ESPBTUUID> &get_service_data_uuid() const;
|
const optional<ESPBTUUID> &get_service_data_uuid() const;
|
||||||
|
const optional<ESPBLEiBeacon> get_ibeacon() const {
|
||||||
|
return ESPBLEiBeacon::from_manufacturer_data(this->manufacturer_data_);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void parse_adv_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param ¶m);
|
||||||
|
|
||||||
esp_bd_addr_t address_{
|
esp_bd_addr_t address_{
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
@ -72,28 +97,28 @@ class ESP32BLETracker;
|
||||||
|
|
||||||
class ESPBTDeviceListener {
|
class ESPBTDeviceListener {
|
||||||
public:
|
public:
|
||||||
ESPBTDeviceListener(ESP32BLETracker *parent) : parent_(parent) {}
|
|
||||||
void setup_ble();
|
|
||||||
virtual void on_scan_end() {}
|
virtual void on_scan_end() {}
|
||||||
virtual bool parse_device(const ESPBTDevice &device) = 0;
|
virtual bool parse_device(const ESPBTDevice &device) = 0;
|
||||||
|
void set_parent(ESP32BLETracker *parent) { parent_ = parent; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ESP32BLETracker *parent_;
|
ESP32BLETracker *parent_{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
class ESP32BLETracker : public Component {
|
class ESP32BLETracker : public Component {
|
||||||
public:
|
public:
|
||||||
void set_scan_interval(uint32_t scan_interval);
|
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.
|
/// Setup the FreeRTOS task and the Bluetooth stack.
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
|
|
||||||
void loop() 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);
|
void print_bt_device_info(const ESPBTDevice &device);
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,8 @@
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace esp32_hall {
|
namespace esp32_hall {
|
||||||
|
|
||||||
class ESP32HallSensor : public sensor::PollingSensorComponent {
|
class ESP32HallSensor : public sensor::Sensor, public PollingComponent {
|
||||||
public:
|
public:
|
||||||
explicit ESP32HallSensor(const std::string &name, uint32_t update_interval)
|
|
||||||
: sensor::PollingSensorComponent(name, update_interval) {}
|
|
||||||
|
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
|
|
||||||
void update() override;
|
void update() override;
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components import sensor
|
from esphome.components import sensor
|
||||||
from esphome.const import CONF_ID, CONF_NAME, CONF_UPDATE_INTERVAL, ESP_PLATFORM_ESP32, \
|
from esphome.const import CONF_ID, ESP_PLATFORM_ESP32, UNIT_MICROTESLA, ICON_MAGNET
|
||||||
UNIT_MICROTESLA, ICON_MAGNET
|
|
||||||
|
|
||||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||||
|
|
||||||
esp32_hall_ns = cg.esphome_ns.namespace('esp32_hall')
|
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({
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_MICROTESLA, ICON_MAGNET, 1).extend({
|
||||||
cv.GenerateID(): cv.declare_id(ESP32HallSensor),
|
cv.GenerateID(): cv.declare_id(ESP32HallSensor),
|
||||||
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval,
|
}).extend(cv.polling_component_schema('60s'))
|
||||||
}).extend(cv.COMPONENT_SCHEMA)
|
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
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 cg.register_component(var, config)
|
||||||
yield sensor.register_sensor(var, config)
|
yield sensor.register_sensor(var, config)
|
||||||
|
|
|
@ -4,6 +4,8 @@ from esphome import pins
|
||||||
from esphome.components import fastled_base
|
from esphome.components import fastled_base
|
||||||
from esphome.const import CONF_CHIPSET, CONF_NUM_LEDS, CONF_PIN, CONF_RGB_ORDER
|
from esphome.const import CONF_CHIPSET, CONF_NUM_LEDS, CONF_PIN, CONF_RGB_ORDER
|
||||||
|
|
||||||
|
AUTO_LOAD = ['fastled_base']
|
||||||
|
|
||||||
CHIPSETS = [
|
CHIPSETS = [
|
||||||
'NEOPIXEL',
|
'NEOPIXEL',
|
||||||
'TM1829',
|
'TM1829',
|
||||||
|
|
|
@ -5,7 +5,7 @@ from esphome.components import sensor
|
||||||
from esphome.const import CONF_CLK_PIN, CONF_GAIN, CONF_ID, ICON_SCALE
|
from esphome.const import CONF_CLK_PIN, CONF_GAIN, CONF_ID, ICON_SCALE
|
||||||
|
|
||||||
hx711_ns = cg.esphome_ns.namespace('hx711')
|
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'
|
CONF_DOUT_PIN = 'dout_pin'
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@ ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||||
|
|
||||||
|
|
||||||
def validate_frequency_bit_depth(obj):
|
def validate_frequency_bit_depth(obj):
|
||||||
frequency = obj.get(CONF_FREQUENCY, 1000)
|
frequency = obj[CONF_FREQUENCY]
|
||||||
bit_depth = obj.get(CONF_BIT_DEPTH, 12)
|
bit_depth = obj[CONF_BIT_DEPTH]
|
||||||
max_freq = APB_CLOCK_FREQ / (2**bit_depth)
|
max_freq = APB_CLOCK_FREQ / (2**bit_depth)
|
||||||
if frequency > max_freq:
|
if frequency > max_freq:
|
||||||
raise cv.Invalid('Maximum frequency for bit depth {} is {}Hz'.format(bit_depth, 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 {
|
void play(Ts... x) override {
|
||||||
auto *out = (AddressableLight *) this->parent_->get_output();
|
auto *out = (AddressableLight *) this->parent_->get_output();
|
||||||
int32_t range_from = this->range_from_.value_or(x..., 0);
|
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);
|
auto range = out->range(range_from, range_to);
|
||||||
if (this->red_.has_value())
|
if (this->red_.has_value())
|
||||||
range.set_red(this->red_.value(x...));
|
range.set_red(this->red_.value(x...));
|
||||||
|
|
|
@ -3,8 +3,9 @@ import esphome.config_validation as cv
|
||||||
from esphome import automation
|
from esphome import automation
|
||||||
from esphome.const import CONF_ID, CONF_TRANSITION_LENGTH, CONF_STATE, CONF_FLASH_LENGTH, \
|
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_EFFECT, CONF_BRIGHTNESS, CONF_RED, CONF_GREEN, CONF_BLUE, CONF_WHITE, \
|
||||||
CONF_COLOR_TEMPERATURE
|
CONF_COLOR_TEMPERATURE, CONF_RANGE_FROM, CONF_RANGE_TO
|
||||||
from .types import DimRelativeAction, ToggleAction, LightState, LightControlAction
|
from .types import DimRelativeAction, ToggleAction, LightState, LightControlAction, \
|
||||||
|
AddressableLightState, AddressableSet
|
||||||
|
|
||||||
|
|
||||||
@automation.register_action('light.toggle', ToggleAction, automation.maybe_simple_id({
|
@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'
|
CONF_RELATIVE_BRIGHTNESS = 'relative_brightness'
|
||||||
LIGHT_DIM_RELATIVE_ACTION_SCHEMA = cv.Schema({
|
LIGHT_DIM_RELATIVE_ACTION_SCHEMA = cv.Schema({
|
||||||
cv.Required(CONF_ID): cv.use_id(LightState),
|
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),
|
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)
|
templ = yield cg.templatable(config[CONF_TRANSITION_LENGTH], args, cg.uint32)
|
||||||
cg.add(var.set_transition_length(templ))
|
cg.add(var.set_transition_length(templ))
|
||||||
yield var
|
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)
|
ToggleAction = light_ns.class_('ToggleAction', automation.Action)
|
||||||
LightControlAction = light_ns.class_('LightControlAction', automation.Action)
|
LightControlAction = light_ns.class_('LightControlAction', automation.Action)
|
||||||
DimRelativeAction = light_ns.class_('DimRelativeAction', automation.Action)
|
DimRelativeAction = light_ns.class_('DimRelativeAction', automation.Action)
|
||||||
|
AddressableSet = light_ns.class_('AddressableSet', automation.Action)
|
||||||
|
|
||||||
# Effects
|
# Effects
|
||||||
LightEffect = light_ns.class_('LightEffect')
|
LightEffect = light_ns.class_('LightEffect')
|
||||||
|
|
|
@ -71,6 +71,7 @@ def validate_local_no_higher_than_global(value):
|
||||||
|
|
||||||
Logger = logger_ns.class_('Logger', cg.Component)
|
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({
|
CONFIG_SCHEMA = cv.All(cv.Schema({
|
||||||
cv.GenerateID(): cv.declare_id(Logger),
|
cv.GenerateID(): cv.declare_id(Logger),
|
||||||
cv.Optional(CONF_BAUD_RATE, default=115200): cv.positive_int,
|
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_LEVEL, default='DEBUG'): is_log_level,
|
||||||
cv.Optional(CONF_LOGS, default={}): cv.Schema({
|
cv.Optional(CONF_LOGS, default={}): cv.Schema({
|
||||||
cv.string: is_log_level,
|
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)
|
}).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')
|
cg.add_build_flag('-DCORE_DEBUG_LEVEL=5')
|
||||||
if CORE.is_esp32 and is_at_least_very_verbose:
|
if CORE.is_esp32 and is_at_least_very_verbose:
|
||||||
cg.add_build_flag('-DENABLE_I2C_DEBUG_BUFFER')
|
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')
|
cg.add_build_flag('-DUSE_STORE_LOG_STR_IN_FLASH')
|
||||||
|
|
||||||
# Register at end for safe mode
|
# 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
|
from esphome.const import CONF_ID, ICON_THERMOMETER, UNIT_CELSIUS
|
||||||
|
|
||||||
max31855_ns = cg.esphome_ns.namespace('max31855')
|
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({
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({
|
||||||
cv.GenerateID(): cv.declare_id(MAX31855Sensor),
|
cv.GenerateID(): cv.declare_id(MAX31855Sensor),
|
||||||
|
|
|
@ -14,7 +14,7 @@ void MAX6675Sensor::update() {
|
||||||
|
|
||||||
// Conversion time typ: 170ms, max: 220ms
|
// Conversion time typ: 170ms, max: 220ms
|
||||||
auto f = std::bind(&MAX6675Sensor::read_data_, this);
|
auto f = std::bind(&MAX6675Sensor::read_data_, this);
|
||||||
this->set_timeout("value", 220, f);
|
this->set_timeout("value", 250, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MAX6675Sensor::setup() {
|
void MAX6675Sensor::setup() {
|
||||||
|
|
|
@ -4,7 +4,7 @@ from esphome.components import sensor, spi
|
||||||
from esphome.const import CONF_ID, ICON_THERMOMETER, UNIT_CELSIUS
|
from esphome.const import CONF_ID, ICON_THERMOMETER, UNIT_CELSIUS
|
||||||
|
|
||||||
max6675_ns = cg.esphome_ns.namespace('max6675')
|
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)
|
spi.SPIDevice)
|
||||||
|
|
||||||
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({
|
||||||
|
|
|
@ -99,17 +99,18 @@ void MPU6050Component::dump_config() {
|
||||||
|
|
||||||
void MPU6050Component::update() {
|
void MPU6050Component::update() {
|
||||||
ESP_LOGV(TAG, " Updating MPU6050...");
|
ESP_LOGV(TAG, " Updating MPU6050...");
|
||||||
uint16_t data[7];
|
uint16_t raw_data[7];
|
||||||
if (!this->read_bytes_16(MPU6050_REGISTER_ACCEL_XOUT_H, data, 7)) {
|
if (!this->read_bytes_16(MPU6050_REGISTER_ACCEL_XOUT_H, raw_data, 7)) {
|
||||||
this->status_set_warning();
|
this->status_set_warning();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto *data = reinterpret_cast<int16_t *>(raw_data);
|
||||||
|
|
||||||
float accel_x = data[0] * MPU6050_RANGE_PER_DIGIT_2G * GRAVITY_EARTH;
|
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_y = data[1] * MPU6050_RANGE_PER_DIGIT_2G * GRAVITY_EARTH;
|
||||||
float accel_z = data[2] * 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_x = data[4] * MPU6050_SCALE_DPS_PER_DIGIT_2000;
|
||||||
float gyro_y = data[5] * 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)
|
@coroutine_with_priority(40.0)
|
||||||
def to_code(config):
|
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_library('AsyncMqttClient', '0.8.2')
|
||||||
cg.add_define('USE_MQTT')
|
cg.add_define('USE_MQTT')
|
||||||
cg.add_global(mqtt_ns.using)
|
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_address(config[CONF_BROKER]))
|
||||||
cg.add(var.set_broker_port(config[CONF_PORT]))
|
cg.add(var.set_broker_port(config[CONF_PORT]))
|
||||||
cg.add(var.set_username(config[CONF_USERNAME]))
|
cg.add(var.set_username(config[CONF_USERNAME]))
|
||||||
|
|
|
@ -152,7 +152,7 @@ class NeoPixelRGBLightOutput : public NeoPixelBusLightOutputBase<T_METHOD, T_COL
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
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;
|
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],
|
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_);
|
nullptr, this->effect_data_ + index, &this->correction_);
|
||||||
|
@ -171,7 +171,7 @@ class NeoPixelRGBWLightOutput : public NeoPixelBusLightOutputBase<T_METHOD, T_CO
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
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;
|
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],
|
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_);
|
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];
|
auto &last_seg = this->segments_[this->segments_.size() - 1];
|
||||||
return last_seg.get_dst_offset() + last_seg.get_size();
|
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 lo = 0;
|
||||||
uint32_t hi = this->segments_.size() - 1;
|
uint32_t hi = this->segments_.size() - 1;
|
||||||
while (lo < hi) {
|
while (lo < hi) {
|
||||||
|
@ -61,22 +77,7 @@ class PartitionLightOutput : public light::AddressableLight, public Component {
|
||||||
view.raw_set_color_correction(&this->correction_);
|
view.raw_set_color_correction(&this->correction_);
|
||||||
return view;
|
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_;
|
std::vector<AddressableSegment> segments_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ COUNT_MODES = {
|
||||||
COUNT_MODE_SCHEMA = cv.enum(COUNT_MODES, upper=True)
|
COUNT_MODE_SCHEMA = cv.enum(COUNT_MODES, upper=True)
|
||||||
|
|
||||||
PulseCounterSensor = pulse_counter_ns.class_('PulseCounterSensor',
|
PulseCounterSensor = pulse_counter_ns.class_('PulseCounterSensor',
|
||||||
sensor.PollingSensorComponent)
|
sensor.Sensor, cg.PollingComponent)
|
||||||
|
|
||||||
|
|
||||||
def validate_internal_filter(value):
|
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')
|
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({
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_SECOND, ICON_TIMER, 3).extend({
|
||||||
cv.GenerateID(): cv.declare_id(PulseWidthSensor),
|
cv.GenerateID(): cv.declare_id(PulseWidthSensor),
|
||||||
|
|
|
@ -51,8 +51,6 @@ sensor_ns = cg.esphome_ns.namespace('sensor')
|
||||||
Sensor = sensor_ns.class_('Sensor', cg.Nameable)
|
Sensor = sensor_ns.class_('Sensor', cg.Nameable)
|
||||||
SensorPtr = Sensor.operator('ptr')
|
SensorPtr = Sensor.operator('ptr')
|
||||||
|
|
||||||
PollingSensorComponent = sensor_ns.class_('PollingSensorComponent', cg.PollingComponent, Sensor)
|
|
||||||
|
|
||||||
# Triggers
|
# Triggers
|
||||||
SensorStateTrigger = sensor_ns.class_('SensorStateTrigger', automation.Trigger.template(cg.float_))
|
SensorStateTrigger = sensor_ns.class_('SensorStateTrigger', automation.Trigger.template(cg.float_))
|
||||||
SensorRawStateTrigger = sensor_ns.class_('SensorRawStateTrigger',
|
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 esphome.const import CONF_ID, CONF_LAMBDA, CONF_STATE, UNIT_EMPTY, ICON_EMPTY
|
||||||
from .. import template_ns
|
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({
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_EMPTY, ICON_EMPTY, 1).extend({
|
||||||
cv.GenerateID(): cv.declare_id(TemplateSensor),
|
cv.GenerateID(): cv.declare_id(TemplateSensor),
|
||||||
|
|
|
@ -11,16 +11,6 @@ namespace time {
|
||||||
static const char *TAG = "time";
|
static const char *TAG = "time";
|
||||||
|
|
||||||
RealTimeClock::RealTimeClock() = default;
|
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() {
|
void RealTimeClock::call_setup() {
|
||||||
this->setup_internal_();
|
this->setup_internal_();
|
||||||
setenv("TZ", this->timezone_.c_str(), 1);
|
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();
|
struct tm c_tm = this->to_c_tm();
|
||||||
return ::strftime(buffer, buffer_len, format, &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),
|
return ESPTime{.second = uint8_t(c_tm->tm_sec),
|
||||||
.minute = uint8_t(c_tm->tm_min),
|
.minute = uint8_t(c_tm->tm_min),
|
||||||
.hour = uint8_t(c_tm->tm_hour),
|
.hour = uint8_t(c_tm->tm_hour),
|
||||||
|
|
|
@ -52,7 +52,26 @@ struct ESPTime {
|
||||||
|
|
||||||
bool in_range() const;
|
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();
|
struct tm to_c_tm();
|
||||||
|
|
||||||
|
@ -81,10 +100,13 @@ class RealTimeClock : public Component {
|
||||||
std::string get_timezone() { return this->timezone_; }
|
std::string get_timezone() { return this->timezone_; }
|
||||||
|
|
||||||
/// Get the time in the currently defined 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.
|
/// 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;
|
void call_setup() override;
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,8 @@ def validate_integration_time(value):
|
||||||
return cv.enum(INTEGRATION_TIMES, int=True)(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({
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_LUX, ICON_BRIGHTNESS_5, 1).extend({
|
||||||
cv.GenerateID(): cv.declare_id(TSL2561Sensor),
|
cv.GenerateID(): cv.declare_id(TSL2561Sensor),
|
||||||
|
|
|
@ -9,7 +9,7 @@ CONF_PULSE_TIME = 'pulse_time'
|
||||||
|
|
||||||
ultrasonic_ns = cg.esphome_ns.namespace('ultrasonic')
|
ultrasonic_ns = cg.esphome_ns.namespace('ultrasonic')
|
||||||
UltrasonicSensorComponent = ultrasonic_ns.class_('UltrasonicSensorComponent',
|
UltrasonicSensorComponent = ultrasonic_ns.class_('UltrasonicSensorComponent',
|
||||||
sensor.PollingSensorComponent)
|
sensor.Sensor, cg.PollingComponent)
|
||||||
|
|
||||||
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_METER, ICON_ARROW_EXPAND_VERTICAL, 2).extend({
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_METER, ICON_ARROW_EXPAND_VERTICAL, 2).extend({
|
||||||
cv.GenerateID(): cv.declare_id(UltrasonicSensorComponent),
|
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
|
from esphome.const import CONF_ID, UNIT_SECOND, ICON_TIMER
|
||||||
|
|
||||||
uptime_ns = cg.esphome_ns.namespace('uptime')
|
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({
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_SECOND, ICON_TIMER, 0).extend({
|
||||||
cv.GenerateID(): cv.declare_id(UptimeSensor),
|
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]);
|
sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||||
return buf;
|
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) {
|
bool sta_field_equal(const uint8_t *field_a, const uint8_t *field_b, int len) {
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
|
|
|
@ -164,8 +164,6 @@ class WiFiComponent : public Component {
|
||||||
/// Reconnect WiFi if required.
|
/// Reconnect WiFi if required.
|
||||||
void loop() override;
|
void loop() override;
|
||||||
|
|
||||||
void on_safe_shutdown() override;
|
|
||||||
|
|
||||||
bool has_sta() const;
|
bool has_sta() const;
|
||||||
bool has_ap() const;
|
bool has_ap() const;
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,8 @@ bool WiFiComponent::wifi_sta_connect_(WiFiAP ap) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->wifi_apply_hostname_();
|
||||||
|
|
||||||
err = esp_wifi_connect();
|
err = esp_wifi_connect();
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGW(TAG, "esp_wifi_connect failed! %d", err);
|
ESP_LOGW(TAG, "esp_wifi_connect failed! %d", err);
|
||||||
|
|
|
@ -196,6 +196,8 @@ bool WiFiComponent::wifi_sta_connect_(WiFiAP ap) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->wifi_apply_hostname_();
|
||||||
|
|
||||||
ETS_UART_INTR_DISABLE();
|
ETS_UART_INTR_DISABLE();
|
||||||
ret = wifi_station_connect();
|
ret = wifi_station_connect();
|
||||||
ETS_UART_INTR_ENABLE();
|
ETS_UART_INTR_ENABLE();
|
||||||
|
|
|
@ -5,7 +5,7 @@ from esphome.const import CONF_ID, ICON_WIFI, UNIT_DECIBEL
|
||||||
|
|
||||||
DEPENDENCIES = ['wifi']
|
DEPENDENCIES = ['wifi']
|
||||||
wifi_signal_ns = cg.esphome_ns.namespace('wifi_signal')
|
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({
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_DECIBEL, ICON_WIFI, 0).extend({
|
||||||
cv.GenerateID(): cv.declare_id(WiFiSignalSensor),
|
cv.GenerateID(): cv.declare_id(WiFiSignalSensor),
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESPBTDeviceListener, \
|
from esphome.components import esp32_ble_tracker
|
||||||
ESP_BLE_DEVICE_SCHEMA
|
|
||||||
from esphome.const import CONF_ID
|
from esphome.const import CONF_ID
|
||||||
|
|
||||||
DEPENDENCIES = ['esp32_ble_tracker']
|
DEPENDENCIES = ['esp32_ble_tracker']
|
||||||
|
|
||||||
xiaomi_ble_ns = cg.esphome_ns.namespace('xiaomi_ble')
|
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({
|
CONFIG_SCHEMA = cv.Schema({
|
||||||
cv.GenerateID(): cv.declare_id(XiaomiListener),
|
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):
|
def to_code(config):
|
||||||
hub = yield cg.get_variable(config[CONF_ESP32_BLE_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
var = cg.new_Pvariable(config[CONF_ID], hub)
|
yield esp32_ble_tracker.register_ble_device(var, config)
|
||||||
yield cg.register_component(var, config)
|
|
||||||
|
|
|
@ -138,8 +138,6 @@ bool XiaomiListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void XiaomiListener::setup() { this->setup_ble(); }
|
|
||||||
XiaomiListener::XiaomiListener(esp32_ble_tracker::ESP32BLETracker *parent) : ESPBTDeviceListener(parent) {}
|
|
||||||
|
|
||||||
} // namespace xiaomi_ble
|
} // namespace xiaomi_ble
|
||||||
} // namespace esphome
|
} // 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);
|
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:
|
public:
|
||||||
XiaomiListener(esp32_ble_tracker::ESP32BLETracker *parent);
|
|
||||||
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
|
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
|
||||||
void setup() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xiaomi_ble
|
} // namespace xiaomi_ble
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components import sensor
|
from esphome.components import sensor, esp32_ble_tracker
|
||||||
from esphome.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESPBTDeviceListener, \
|
|
||||||
ESP_BLE_DEVICE_SCHEMA
|
|
||||||
from esphome.const import CONF_BATTERY_LEVEL, CONF_MAC_ADDRESS, CONF_TEMPERATURE, \
|
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, \
|
UNIT_CELSIUS, ICON_THERMOMETER, UNIT_PERCENT, ICON_WATER_PERCENT, ICON_BATTERY, CONF_ID, \
|
||||||
CONF_MOISTURE, CONF_ILLUMINANCE, ICON_BRIGHTNESS_5, UNIT_LUX, CONF_CONDUCTIVITY, \
|
CONF_MOISTURE, CONF_ILLUMINANCE, ICON_BRIGHTNESS_5, UNIT_LUX, CONF_CONDUCTIVITY, \
|
||||||
|
@ -12,7 +10,8 @@ DEPENDENCIES = ['esp32_ble_tracker']
|
||||||
AUTO_LOAD = ['xiaomi_ble']
|
AUTO_LOAD = ['xiaomi_ble']
|
||||||
|
|
||||||
xiaomi_miflora_ns = cg.esphome_ns.namespace('xiaomi_miflora')
|
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({
|
CONFIG_SCHEMA = cv.Schema({
|
||||||
cv.GenerateID(): cv.declare_id(XiaomiMiflora),
|
cv.GenerateID(): cv.declare_id(XiaomiMiflora),
|
||||||
|
@ -23,13 +22,15 @@ CONFIG_SCHEMA = cv.Schema({
|
||||||
cv.Optional(CONF_CONDUCTIVITY):
|
cv.Optional(CONF_CONDUCTIVITY):
|
||||||
sensor.sensor_schema(UNIT_MICROSIEMENS_PER_CENTIMETER, ICON_FLOWER, 0),
|
sensor.sensor_schema(UNIT_MICROSIEMENS_PER_CENTIMETER, ICON_FLOWER, 0),
|
||||||
cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(UNIT_PERCENT, ICON_BATTERY, 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):
|
def to_code(config):
|
||||||
hub = yield cg.get_variable(config[CONF_ESP32_BLE_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
var = cg.new_Pvariable(config[CONF_ID], hub, config[CONF_MAC_ADDRESS].as_hex)
|
|
||||||
yield cg.register_component(var, config)
|
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:
|
if CONF_TEMPERATURE in config:
|
||||||
sens = yield sensor.new_sensor(config[CONF_TEMPERATURE])
|
sens = yield sensor.new_sensor(config[CONF_TEMPERATURE])
|
||||||
|
|
|
@ -12,8 +12,7 @@ namespace xiaomi_miflora {
|
||||||
|
|
||||||
class XiaomiMiflora : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
|
class XiaomiMiflora : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
|
||||||
public:
|
public:
|
||||||
XiaomiMiflora(esp32_ble_tracker::ESP32BLETracker *parent, uint64_t address)
|
void set_address(uint64_t address) { address_ = address; }
|
||||||
: ESPBTDeviceListener(parent), address_(address) {}
|
|
||||||
|
|
||||||
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override {
|
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override {
|
||||||
if (device.address_uint64() != this->address_)
|
if (device.address_uint64() != this->address_)
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components import sensor
|
from esphome.components import sensor, esp32_ble_tracker
|
||||||
from esphome.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESPBTDeviceListener, \
|
|
||||||
ESP_BLE_DEVICE_SCHEMA
|
|
||||||
from esphome.const import CONF_BATTERY_LEVEL, CONF_HUMIDITY, CONF_MAC_ADDRESS, CONF_TEMPERATURE, \
|
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
|
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']
|
AUTO_LOAD = ['xiaomi_ble']
|
||||||
|
|
||||||
xiaomi_mijia_ns = cg.esphome_ns.namespace('xiaomi_mijia')
|
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({
|
CONFIG_SCHEMA = cv.Schema({
|
||||||
cv.GenerateID(): cv.declare_id(XiaomiMijia),
|
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_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_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 1),
|
||||||
cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(UNIT_PERCENT, ICON_BATTERY, 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):
|
def to_code(config):
|
||||||
hub = yield cg.get_variable(config[CONF_ESP32_BLE_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
var = cg.new_Pvariable(config[CONF_ID], hub, config[CONF_MAC_ADDRESS].as_hex)
|
|
||||||
yield cg.register_component(var, config)
|
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:
|
if CONF_TEMPERATURE in config:
|
||||||
sens = yield sensor.new_sensor(config[CONF_TEMPERATURE])
|
sens = yield sensor.new_sensor(config[CONF_TEMPERATURE])
|
||||||
|
|
|
@ -12,8 +12,7 @@ namespace xiaomi_mijia {
|
||||||
|
|
||||||
class XiaomiMijia : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
|
class XiaomiMijia : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
|
||||||
public:
|
public:
|
||||||
XiaomiMijia(esp32_ble_tracker::ESP32BLETracker *parent, uint64_t address)
|
void set_address(uint64_t address) { address_ = address; }
|
||||||
: ESPBTDeviceListener(parent), address_(address) {}
|
|
||||||
|
|
||||||
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override {
|
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override {
|
||||||
if (device.address_uint64() != this->address_)
|
if (device.address_uint64() != this->address_)
|
||||||
|
|
|
@ -317,6 +317,8 @@ CONF_PULSE_LENGTH = 'pulse_length'
|
||||||
CONF_QOS = 'qos'
|
CONF_QOS = 'qos'
|
||||||
CONF_RANDOM = 'random'
|
CONF_RANDOM = 'random'
|
||||||
CONF_RANGE = 'range'
|
CONF_RANGE = 'range'
|
||||||
|
CONF_RANGE_FROM = 'range_from'
|
||||||
|
CONF_RANGE_TO = 'range_to'
|
||||||
CONF_RATE = 'rate'
|
CONF_RATE = 'rate'
|
||||||
CONF_RAW = 'raw'
|
CONF_RAW = 'raw'
|
||||||
CONF_REBOOT_TIMEOUT = 'reboot_timeout'
|
CONF_REBOOT_TIMEOUT = 'reboot_timeout'
|
||||||
|
|
|
@ -55,7 +55,7 @@ template<typename... Ts> class Trigger {
|
||||||
bool is_running() {
|
bool is_running() {
|
||||||
if (this->automation_parent_ == nullptr)
|
if (this->automation_parent_ == nullptr)
|
||||||
return false;
|
return false;
|
||||||
return this->automation_parent_.is_running();
|
return this->automation_parent_->is_running();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#define HOT __attribute__((hot))
|
#define HOT __attribute__((hot))
|
||||||
#define ESPDEPRECATED(msg) __attribute__((deprecated(msg)))
|
#define ESPDEPRECATED(msg) __attribute__((deprecated(msg)))
|
||||||
#define ALWAYS_INLINE __attribute__((always_inline))
|
#define ALWAYS_INLINE __attribute__((always_inline))
|
||||||
|
#define PACKED __attribute__((packed))
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
|
||||||
|
|
|
@ -152,7 +152,7 @@ def add_includes(includes):
|
||||||
for include in includes:
|
for include in includes:
|
||||||
path = CORE.relative_config_path(include)
|
path = CORE.relative_config_path(include)
|
||||||
res = os.path.relpath(path, CORE.relative_build_path('src')).replace(os.path.sep, '/')
|
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)
|
@coroutine_with_priority(100.0)
|
||||||
|
|
|
@ -430,6 +430,9 @@ const validateModal = new LogModalElem({
|
||||||
name: 'validate',
|
name: 'validate',
|
||||||
onPrepare: (modalElem, config) => {
|
onPrepare: (modalElem, config) => {
|
||||||
modalElem.querySelector(".stop-logs").innerHTML = "Stop";
|
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) => {
|
onProcessExit: (modalElem, code) => {
|
||||||
if (code === 0) {
|
if (code === 0) {
|
||||||
|
@ -437,6 +440,7 @@ const validateModal = new LogModalElem({
|
||||||
html: `<code class="inlinecode">${validateModal.activeConfig}</code> is valid 👍`,
|
html: `<code class="inlinecode">${validateModal.activeConfig}</code> is valid 👍`,
|
||||||
displayLength: 5000,
|
displayLength: 5000,
|
||||||
});
|
});
|
||||||
|
modalElem.querySelector(".action-upload").classList.remove('disabled');
|
||||||
} else {
|
} else {
|
||||||
M.toast({
|
M.toast({
|
||||||
html: `<code class="inlinecode">${validateModal.activeConfig}</code> is invalid 😕`,
|
html: `<code class="inlinecode">${validateModal.activeConfig}</code> is invalid 😕`,
|
||||||
|
@ -552,6 +556,7 @@ editor.session.setOption('useSoftTabs', true);
|
||||||
editor.session.setOption('tabSize', 2);
|
editor.session.setOption('tabSize', 2);
|
||||||
|
|
||||||
const saveButton = editModalElem.querySelector(".save-button");
|
const saveButton = editModalElem.querySelector(".save-button");
|
||||||
|
const saveValidateButton = editModalElem.querySelector(".save-validate-button");
|
||||||
const saveEditor = () => {
|
const saveEditor = () => {
|
||||||
fetch(`./edit?configuration=${activeEditorConfig}`, {
|
fetch(`./edit?configuration=${activeEditorConfig}`, {
|
||||||
credentials: "same-origin",
|
credentials: "same-origin",
|
||||||
|
@ -572,12 +577,14 @@ editor.commands.addCommand({
|
||||||
});
|
});
|
||||||
|
|
||||||
saveButton.addEventListener('click', saveEditor);
|
saveButton.addEventListener('click', saveEditor);
|
||||||
|
saveValidateButton.addEventListener('click', saveEditor);
|
||||||
|
|
||||||
document.querySelectorAll(".action-edit").forEach((btn) => {
|
document.querySelectorAll(".action-edit").forEach((btn) => {
|
||||||
btn.addEventListener('click', (e) => {
|
btn.addEventListener('click', (e) => {
|
||||||
activeEditorConfig = e.target.getAttribute('data-node');
|
activeEditorConfig = e.target.getAttribute('data-node');
|
||||||
const modalInstance = M.Modal.getInstance(editModalElem);
|
const modalInstance = M.Modal.getInstance(editModalElem);
|
||||||
const filenameField = editModalElem.querySelector('.filename');
|
const filenameField = editModalElem.querySelector('.filename');
|
||||||
|
editModalElem.querySelector(".save-validate-button").setAttribute('data-node', activeEditorConfig);
|
||||||
filenameField.innerHTML = activeEditorConfig;
|
filenameField.innerHTML = activeEditorConfig;
|
||||||
|
|
||||||
fetch(`./edit?configuration=${activeEditorConfig}`, {credentials: "same-origin"})
|
fetch(`./edit?configuration=${activeEditorConfig}`, {credentials: "same-origin"})
|
||||||
|
|
|
@ -147,6 +147,8 @@
|
||||||
<pre class="log"></pre>
|
<pre class="log"></pre>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<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>
|
<a class="modal-close waves-effect waves-green btn-flat stop-logs">Stop</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -430,6 +432,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<a class="waves-effect waves-green btn-flat save-button">Save</a>
|
<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>
|
<a class="modal-close waves-effect waves-green btn-flat">Close</a>
|
||||||
</div>
|
</div>
|
||||||
</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 root, _, fs in os.walk('esphome'):
|
||||||
for f in fs:
|
for f in fs:
|
||||||
_, ext = os.path.splitext(f)
|
_, 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))
|
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()
|
files.sort()
|
||||||
|
|
||||||
errors = collections.defaultdict(list)
|
errors = collections.defaultdict(list)
|
||||||
|
|
|
@ -45,6 +45,8 @@ def run_tidy(args, tmpdir, queue, lock, failed_files):
|
||||||
invocation.append('-p=.')
|
invocation.append('-p=.')
|
||||||
if args.quiet:
|
if args.quiet:
|
||||||
invocation.append('-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.append(os.path.abspath(path))
|
||||||
invocation_s = ' '.join(shlex_quote(x) for x in invocation)
|
invocation_s = ' '.join(shlex_quote(x) for x in invocation)
|
||||||
|
|
||||||
|
@ -135,9 +137,6 @@ def build_compile_commands():
|
||||||
command.append('-Wall')
|
command.append('-Wall')
|
||||||
command.append('-Wno-delete-non-virtual-dtor')
|
command.append('-Wno-delete-non-virtual-dtor')
|
||||||
command.append('-Wno-unused-variable')
|
command.append('-Wno-unused-variable')
|
||||||
command.append('-Wfor-loop-analysis')
|
|
||||||
command.append('-Wshadow-field')
|
|
||||||
command.append('-Wshadow-field-in-constructor')
|
|
||||||
command.append('-Wunreachable-code')
|
command.append('-Wunreachable-code')
|
||||||
|
|
||||||
source_files = []
|
source_files = []
|
||||||
|
@ -265,8 +264,6 @@ def main():
|
||||||
print('Ctrl-C detected, goodbye.')
|
print('Ctrl-C detected, goodbye.')
|
||||||
if tmpdir:
|
if tmpdir:
|
||||||
shutil.rmtree(tmpdir)
|
shutil.rmtree(tmpdir)
|
||||||
if os.path.exists(temp_header_file):
|
|
||||||
os.remove(temp_header_file)
|
|
||||||
os.kill(0, 9)
|
os.kill(0, 9)
|
||||||
|
|
||||||
if args.fix and failed_files:
|
if args.fix and failed_files:
|
||||||
|
@ -275,12 +272,8 @@ def main():
|
||||||
subprocess.call(['clang-apply-replacements-7', tmpdir])
|
subprocess.call(['clang-apply-replacements-7', tmpdir])
|
||||||
except:
|
except:
|
||||||
print('Error applying fixes.\n', file=sys.stderr)
|
print('Error applying fixes.\n', file=sys.stderr)
|
||||||
if os.path.exists(temp_header_file):
|
|
||||||
os.remove(temp_header_file)
|
|
||||||
raise
|
raise
|
||||||
|
|
||||||
if os.path.exists(temp_header_file):
|
|
||||||
os.remove(temp_header_file)
|
|
||||||
sys.exit(return_code)
|
sys.exit(return_code)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,5 +12,5 @@ fi
|
||||||
|
|
||||||
set -x
|
set -x
|
||||||
|
|
||||||
script/clang-tidy.py -c --fix
|
script/clang-tidy.py -c --fix --all-headers
|
||||||
script/clang-format.py -c -i
|
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:
|
- wait_until:
|
||||||
- api.connected
|
- api.connected
|
||||||
- wifi.connected
|
- wifi.connected
|
||||||
|
includes:
|
||||||
|
- custom.h
|
||||||
|
|
||||||
substitutions:
|
substitutions:
|
||||||
devicename: test3
|
devicename: test3
|
||||||
|
@ -65,6 +67,7 @@ ota:
|
||||||
logger:
|
logger:
|
||||||
hardware_uart: UART1
|
hardware_uart: UART1
|
||||||
level: DEBUG
|
level: DEBUG
|
||||||
|
esp8266_store_log_strings_in_flash: false
|
||||||
|
|
||||||
web_server:
|
web_server:
|
||||||
|
|
||||||
|
@ -122,6 +125,14 @@ sensor:
|
||||||
name: Color Temperature
|
name: Color Temperature
|
||||||
integration_time: 700ms
|
integration_time: 700ms
|
||||||
gain: 60x
|
gain: 60x
|
||||||
|
- platform: custom
|
||||||
|
lambda: |-
|
||||||
|
auto s = new CustomSensor();
|
||||||
|
App.register_component(s);
|
||||||
|
return {s};
|
||||||
|
sensors:
|
||||||
|
- id: custom_sensor
|
||||||
|
name: Custom Sensor
|
||||||
|
|
||||||
time:
|
time:
|
||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
|
@ -178,6 +189,14 @@ binary_sensor:
|
||||||
- platform: ttp229_lsf
|
- platform: ttp229_lsf
|
||||||
channel: 1
|
channel: 1
|
||||||
name: TTP229 LSF Test
|
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:
|
remote_receiver:
|
||||||
pin: GPIO12
|
pin: GPIO12
|
||||||
|
@ -211,6 +230,14 @@ text_sensor:
|
||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
entity_id: sensor.hello_world2
|
entity_id: sensor.hello_world2
|
||||||
id: ha_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:
|
script:
|
||||||
- id: my_script
|
- id: my_script
|
||||||
|
@ -233,6 +260,19 @@ switch:
|
||||||
id: gpio_switch2
|
id: gpio_switch2
|
||||||
pin: GPIO1
|
pin: GPIO1
|
||||||
interlock: *interlock
|
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:
|
stepper:
|
||||||
- platform: uln2003
|
- platform: uln2003
|
||||||
|
|
Loading…
Reference in a new issue