🏗 Merge C++ into python codebase (#504)

## Description:

Move esphome-core codebase into esphome (and a bunch of other refactors). See https://github.com/esphome/feature-requests/issues/97

Yes this is a shit ton of work and no there's no way to automate it :( But it will be worth it 👍

Progress:
- Core support (file copy etc): 80%
- Base Abstractions (light, switch): ~50%
- Integrations: ~10%
- Working? Yes, (but only with ported components).

Other refactors:
- Moves all codegen related stuff into a single class: `esphome.codegen` (imported as `cg`)
- Rework coroutine syntax
- Move from `component/platform.py` to `domain/component.py` structure as with HA
- Move all defaults out of C++ and into config validation.
- Remove `make_...` helpers from Application class. Reason: Merge conflicts with every single new integration.
- Pointer Variables are stored globally instead of locally in setup(). Reason: stack size limit.

Future work:
- Rework const.py - Move all `CONF_...` into a conf class (usage `conf.UPDATE_INTERVAL` vs `CONF_UPDATE_INTERVAL`). Reason: Less convoluted import block
- Enable loading from `custom_components` folder.

**Related issue (if applicable):** https://github.com/esphome/feature-requests/issues/97

**Pull request in [esphome-docs](https://github.com/esphome/esphome-docs) with documentation (if applicable):** esphome/esphome-docs#<esphome-docs PR number goes here>

## Checklist:
  - [ ] The code change is tested and works locally.
  - [ ] Tests have been added to verify that the new code works (under `tests/` folder).

If user exposed functionality or configuration variables are added/changed:
  - [ ] Documentation added/updated in [esphomedocs](https://github.com/OttoWinter/esphomedocs).
This commit is contained in:
Otto Winter
2019-04-17 12:06:00 +02:00
committed by GitHub
parent 049807e3ab
commit 6682c43dfa
817 changed files with 54156 additions and 10830 deletions
+48 -67
View File
@@ -1,108 +1,89 @@
import voluptuous as vol
from esphome.automation import ACTION_REGISTRY, maybe_simple_id
from esphome.components.power_supply import PowerSupplyComponent
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.automation import ACTION_REGISTRY, maybe_simple_id
from esphome.components import power_supply
from esphome.const import CONF_ID, CONF_INVERTED, CONF_LEVEL, CONF_MAX_POWER, \
CONF_MIN_POWER, CONF_POWER_SUPPLY
from esphome.core import CORE
from esphome.cpp_generator import Pvariable, add, get_variable, templatable
from esphome.cpp_types import Action, esphome_ns, float_
from esphome.core import CORE, coroutine
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
})
IS_PLATFORM_COMPONENT = True
BINARY_OUTPUT_SCHEMA = cv.Schema({
vol.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(PowerSupplyComponent),
vol.Optional(CONF_INVERTED): cv.boolean,
cv.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(power_supply.PowerSupply),
cv.Optional(CONF_INVERTED): cv.boolean,
})
BINARY_OUTPUT_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(BINARY_OUTPUT_SCHEMA.schema)
FLOAT_OUTPUT_SCHEMA = BINARY_OUTPUT_SCHEMA.extend({
vol.Optional(CONF_MAX_POWER): cv.percentage,
vol.Optional(CONF_MIN_POWER): cv.percentage,
cv.Optional(CONF_MAX_POWER): cv.percentage,
cv.Optional(CONF_MIN_POWER): cv.percentage,
})
FLOAT_OUTPUT_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(FLOAT_OUTPUT_SCHEMA.schema)
output_ns = esphome_ns.namespace('output')
output_ns = cg.esphome_ns.namespace('output')
BinaryOutput = output_ns.class_('BinaryOutput')
BinaryOutputPtr = BinaryOutput.operator('ptr')
FloatOutput = output_ns.class_('FloatOutput', BinaryOutput)
FloatOutputPtr = FloatOutput.operator('ptr')
# Actions
TurnOffAction = output_ns.class_('TurnOffAction', Action)
TurnOnAction = output_ns.class_('TurnOnAction', Action)
SetLevelAction = output_ns.class_('SetLevelAction', Action)
TurnOffAction = output_ns.class_('TurnOffAction', cg.Action)
TurnOnAction = output_ns.class_('TurnOnAction', cg.Action)
SetLevelAction = output_ns.class_('SetLevelAction', cg.Action)
def setup_output_platform_(obj, config, skip_power_supply=False):
@coroutine
def setup_output_platform_(obj, config):
if CONF_INVERTED in config:
add(obj.set_inverted(config[CONF_INVERTED]))
if not skip_power_supply and CONF_POWER_SUPPLY in config:
power_supply = yield get_variable(config[CONF_POWER_SUPPLY])
add(obj.set_power_supply(power_supply))
cg.add(obj.set_inverted(config[CONF_INVERTED]))
if CONF_POWER_SUPPLY in config:
power_supply_ = yield cg.get_variable(config[CONF_POWER_SUPPLY])
cg.add(obj.set_power_supply(power_supply_))
if CONF_MAX_POWER in config:
add(obj.set_max_power(config[CONF_MAX_POWER]))
cg.add(obj.set_max_power(config[CONF_MAX_POWER]))
if CONF_MIN_POWER in config:
add(obj.set_min_power(config[CONF_MIN_POWER]))
def setup_output_platform(obj, config, skip_power_supply=False):
CORE.add_job(setup_output_platform_, obj, config, skip_power_supply)
cg.add(obj.set_min_power(config[CONF_MIN_POWER]))
@coroutine
def register_output(var, config):
output_var = Pvariable(config[CONF_ID], var, has_side_effects=True)
CORE.add_job(setup_output_platform_, output_var, config)
if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var)
yield setup_output_platform_(var, config)
BUILD_FLAGS = '-DUSE_OUTPUT'
CONF_OUTPUT_TURN_ON = 'output.turn_on'
OUTPUT_TURN_ON_ACTION = maybe_simple_id({
vol.Required(CONF_ID): cv.use_variable_id(BinaryOutput),
BINARY_OUTPUT_ACTION_SCHEMA = maybe_simple_id({
cv.Required(CONF_ID): cv.use_variable_id(BinaryOutput),
})
@ACTION_REGISTRY.register(CONF_OUTPUT_TURN_ON, OUTPUT_TURN_ON_ACTION)
@ACTION_REGISTRY.register('output.turn_on', BINARY_OUTPUT_ACTION_SCHEMA)
def output_turn_on_to_code(config, action_id, template_arg, args):
var = yield get_variable(config[CONF_ID])
rhs = var.make_turn_on_action(template_arg)
var = yield cg.get_variable(config[CONF_ID])
type = TurnOnAction.template(template_arg)
yield Pvariable(action_id, rhs, type=type)
rhs = type.new(var)
yield cg.Pvariable(action_id, rhs, type=type)
CONF_OUTPUT_TURN_OFF = 'output.turn_off'
OUTPUT_TURN_OFF_ACTION = maybe_simple_id({
vol.Required(CONF_ID): cv.use_variable_id(BinaryOutput)
})
@ACTION_REGISTRY.register(CONF_OUTPUT_TURN_OFF, OUTPUT_TURN_OFF_ACTION)
@ACTION_REGISTRY.register('output.turn_off', BINARY_OUTPUT_ACTION_SCHEMA)
def output_turn_off_to_code(config, action_id, template_arg, args):
var = yield get_variable(config[CONF_ID])
rhs = var.make_turn_off_action(template_arg)
var = yield cg.get_variable(config[CONF_ID])
type = TurnOffAction.template(template_arg)
yield Pvariable(action_id, rhs, type=type)
rhs = type.new(var)
yield cg.Pvariable(action_id, rhs, type=type)
CONF_OUTPUT_SET_LEVEL = 'output.set_level'
OUTPUT_SET_LEVEL_ACTION = cv.Schema({
vol.Required(CONF_ID): cv.use_variable_id(FloatOutput),
vol.Required(CONF_LEVEL): cv.templatable(cv.percentage),
})
@ACTION_REGISTRY.register(CONF_OUTPUT_SET_LEVEL, OUTPUT_SET_LEVEL_ACTION)
@ACTION_REGISTRY.register('output.set_level', cv.Schema({
cv.Required(CONF_ID): cv.use_variable_id(FloatOutput),
cv.Required(CONF_LEVEL): cv.templatable(cv.percentage),
}))
def output_set_level_to_code(config, action_id, template_arg, args):
var = yield get_variable(config[CONF_ID])
rhs = var.make_set_level_action(template_arg)
var = yield cg.get_variable(config[CONF_ID])
type = SetLevelAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type)
template_ = yield templatable(config[CONF_LEVEL], args, float_)
add(action.set_level(template_))
rhs = type.new(var)
action = cg.Pvariable(action_id, rhs, type=type)
template_ = yield cg.templatable(config[CONF_LEVEL], args, float)
cg.add(action.set_level(template_))
yield action
def to_code(config):
cg.add_global(output_ns.using)
+10
View File
@@ -0,0 +1,10 @@
#include "automation.h"
#include "esphome/core/log.h"
namespace esphome {
namespace output {
static const char *TAG = "output.automation";
} // namespace output
} // namespace esphome
+52
View File
@@ -0,0 +1,52 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/automation.h"
#include "esphome/components/output/binary_output.h"
#include "esphome/components/output/float_output.h"
namespace esphome {
namespace output {
template<typename... Ts> class TurnOffAction : public Action<Ts...> {
public:
TurnOffAction(BinaryOutput *output) : output_(output) {}
void play(Ts... x) override {
this->output_->turn_off();
this->play_next(x...);
}
protected:
BinaryOutput *output_;
};
template<typename... Ts> class TurnOnAction : public Action<Ts...> {
public:
TurnOnAction(BinaryOutput *output) : output_(output) {}
void play(Ts... x) override {
this->output_->turn_on();
this->play_next(x...);
}
protected:
BinaryOutput *output_;
};
template<typename... Ts> class SetLevelAction : public Action<Ts...> {
public:
SetLevelAction(FloatOutput *output) : output_(output) {}
TEMPLATABLE_VALUE(float, level)
void play(Ts... x) override {
this->output_->set_level(this->level_.value(x...));
this->play_next(x...);
}
protected:
FloatOutput *output_;
};
} // namespace output
} // namespace esphome
+71
View File
@@ -0,0 +1,71 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/defines.h"
#ifdef USE_POWER_SUPPLY
#include "esphome/components/power_supply/power_supply.h"
#endif
namespace esphome {
namespace output {
#define LOG_BINARY_OUTPUT(this) \
if (this->inverted_) { \
ESP_LOGCONFIG(TAG, " Inverted: YES"); \
}
class BinaryOutput {
public:
/// Set the inversion state of this binary output.
void set_inverted(bool inverted) { this->inverted_ = inverted; }
#ifdef USE_POWER_SUPPLY
/** Use this to connect up a power supply to this output.
*
* Whenever this output is enabled, the power supply will automatically be turned on.
*
* @param power_supply The PowerSupplyComponent, set this to nullptr to disable the power supply.
*/
void set_power_supply(power_supply::PowerSupply *power_supply) { this->power_supply_ = power_supply; }
#endif
/// Enable this binary output.
virtual void turn_on() {
#ifdef USE_POWER_SUPPLY
if (this->power_supply_ != nullptr && !this->has_requested_high_power_) {
this->power_supply_->request_high_power();
this->has_requested_high_power_ = true;
}
#endif
this->write_state(!this->inverted_);
}
/// Disable this binary output.
virtual void turn_off() {
#ifdef USE_POWER_SUPPLY
if (this->power_supply_ != nullptr && this->has_requested_high_power_) {
this->power_supply_->unrequest_high_power();
this->has_requested_high_power_ = false;
}
#endif
this->write_state(this->inverted_);
}
// ========== INTERNAL METHODS ==========
// (In most use cases you won't need these)
/// Return whether this binary output is inverted.
bool is_inverted() const { return this->inverted_; }
protected:
virtual void write_state(bool state) = 0;
bool inverted_{false};
#ifdef USE_POWER_SUPPLY
power_supply::PowerSupply *power_supply_{nullptr};
bool has_requested_high_power_{false};
#endif
};
} // namespace output
} // namespace esphome
-56
View File
@@ -1,56 +0,0 @@
import voluptuous as vol
from esphome.components import output
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_OUTPUTS, CONF_TYPE
from esphome.cpp_generator import Pvariable, get_variable
from esphome.cpp_helpers import setup_component
BinaryCopyOutput = output.output_ns.class_('BinaryCopyOutput', output.BinaryOutput)
FloatCopyOutput = output.output_ns.class_('FloatCopyOutput', output.FloatOutput)
BINARY_SCHEMA = output.PLATFORM_SCHEMA.extend({
vol.Required(CONF_ID): cv.declare_variable_id(BinaryCopyOutput),
vol.Required(CONF_TYPE): 'binary',
vol.Required(CONF_OUTPUTS): cv.ensure_list(cv.use_variable_id(output.BinaryOutput)),
})
FLOAT_SCHEMA = output.PLATFORM_SCHEMA.extend({
vol.Required(CONF_ID): cv.declare_variable_id(FloatCopyOutput),
vol.Required(CONF_TYPE): 'float',
vol.Required(CONF_OUTPUTS): cv.ensure_list(cv.use_variable_id(output.FloatOutput)),
})
def validate_copy_output(value):
if not isinstance(value, dict):
raise vol.Invalid("Value must be dict")
type = cv.string_strict(value.get(CONF_TYPE, 'float')).lower()
value[CONF_TYPE] = type
if type == 'binary':
return BINARY_SCHEMA(value)
if type == 'float':
return FLOAT_SCHEMA(value)
raise vol.Invalid("type must either be binary or float, not {}!".format(type))
PLATFORM_SCHEMA = validate_copy_output
def to_code(config):
outputs = []
for out in config[CONF_OUTPUTS]:
outputs.append((yield get_variable(out)))
klass = {
'binary': BinaryCopyOutput,
'float': FloatCopyOutput,
}[config[CONF_TYPE]]
rhs = klass.new(outputs)
gpio = Pvariable(config[CONF_ID], rhs)
output.setup_output_platform(gpio, config)
setup_component(gpio, config)
BUILD_FLAGS = '-DUSE_COPY_OUTPUT'
-67
View File
@@ -1,67 +0,0 @@
import voluptuous as vol
from esphome.components import output
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_OUTPUTS, CONF_TYPE
from esphome.cpp_generator import process_lambda, variable
from esphome.cpp_types import std_vector
CustomBinaryOutputConstructor = output.output_ns.class_('CustomBinaryOutputConstructor')
CustomFloatOutputConstructor = output.output_ns.class_('CustomFloatOutputConstructor')
BINARY_SCHEMA = output.PLATFORM_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(CustomBinaryOutputConstructor),
vol.Required(CONF_LAMBDA): cv.lambda_,
vol.Required(CONF_TYPE): 'binary',
vol.Required(CONF_OUTPUTS):
cv.ensure_list(output.BINARY_OUTPUT_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(output.BinaryOutput),
})),
})
FLOAT_SCHEMA = output.PLATFORM_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(CustomFloatOutputConstructor),
vol.Required(CONF_LAMBDA): cv.lambda_,
vol.Required(CONF_TYPE): 'float',
vol.Required(CONF_OUTPUTS):
cv.ensure_list(output.FLOAT_OUTPUT_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(output.FloatOutput),
})),
})
def validate_custom_output(value):
if not isinstance(value, dict):
raise vol.Invalid("Value must be dict")
if CONF_TYPE not in value:
raise vol.Invalid("type not specified!")
type = cv.string_strict(value[CONF_TYPE]).lower()
value[CONF_TYPE] = type
if type == 'binary':
return BINARY_SCHEMA(value)
if type == 'float':
return FLOAT_SCHEMA(value)
raise vol.Invalid("type must either be binary or float, not {}!".format(type))
PLATFORM_SCHEMA = validate_custom_output
def to_code(config):
type = config[CONF_TYPE]
if type == 'binary':
ret_type = output.BinaryOutputPtr
klass = CustomBinaryOutputConstructor
else:
ret_type = output.FloatOutputPtr
klass = CustomFloatOutputConstructor
template_ = yield process_lambda(config[CONF_LAMBDA], [],
return_type=std_vector.template(ret_type))
rhs = klass(template_)
custom = variable(config[CONF_ID], rhs)
for i, conf in enumerate(config[CONF_OUTPUTS]):
output.register_output(custom.get_output(i), conf)
BUILD_FLAGS = '-DUSE_CUSTOM_OUTPUT'
-41
View File
@@ -1,41 +0,0 @@
import voluptuous as vol
from esphome import pins
from esphome.components import output
import esphome.config_validation as cv
from esphome.const import CONF_FREQUENCY, CONF_ID, CONF_NUMBER, CONF_PIN, ESP_PLATFORM_ESP8266
from esphome.cpp_generator import Pvariable, add
from esphome.cpp_helpers import gpio_output_pin_expression, setup_component
from esphome.cpp_types import App, Component
ESP_PLATFORMS = [ESP_PLATFORM_ESP8266]
def valid_pwm_pin(value):
num = value[CONF_NUMBER]
cv.one_of(0, 1, 2, 3, 4, 5, 9, 10, 12, 13, 14, 15, 16)(num)
return value
ESP8266PWMOutput = output.output_ns.class_('ESP8266PWMOutput', output.FloatOutput, Component)
PLATFORM_SCHEMA = output.FLOAT_OUTPUT_PLATFORM_SCHEMA.extend({
vol.Required(CONF_ID): cv.declare_variable_id(ESP8266PWMOutput),
vol.Required(CONF_PIN): vol.All(pins.internal_gpio_output_pin_schema, valid_pwm_pin),
vol.Optional(CONF_FREQUENCY): vol.All(cv.frequency, vol.Range(min=1.0e-6)),
}).extend(cv.COMPONENT_SCHEMA.schema)
def to_code(config):
pin = yield gpio_output_pin_expression(config[CONF_PIN])
rhs = App.make_esp8266_pwm_output(pin)
gpio = Pvariable(config[CONF_ID], rhs)
if CONF_FREQUENCY in config:
add(gpio.set_frequency(config[CONF_FREQUENCY]))
output.setup_output_platform(gpio, config)
setup_component(gpio, config)
BUILD_FLAGS = '-DUSE_ESP8266_PWM_OUTPUT'
@@ -0,0 +1,48 @@
#include "float_output.h"
#include "esphome/core/log.h"
#include "esphome/core/helpers.h"
namespace esphome {
namespace output {
static const char *TAG = "output.float";
void FloatOutput::set_max_power(float max_power) {
this->max_power_ = clamp(max_power, this->min_power_, 1.0f); // Clamp to MIN>=MAX>=1.0
}
float FloatOutput::get_max_power() const { return this->max_power_; }
void FloatOutput::set_min_power(float min_power) {
this->min_power_ = clamp(min_power, 0.0f, this->max_power_); // Clamp to 0.0>=MIN>=MAX
}
float FloatOutput::get_min_power() const { return this->min_power_; }
void FloatOutput::set_level(float state) {
state = clamp(state, 0.0f, 1.0f);
#ifdef USE_POWER_SUPPLY
if (state > 0.0f) { // ON
if (this->power_supply_ != nullptr && !this->has_requested_high_power_) {
this->power_supply_->request_high_power();
this->has_requested_high_power_ = true;
}
} else { // OFF
if (this->power_supply_ != nullptr && this->has_requested_high_power_) {
this->power_supply_->unrequest_high_power();
this->has_requested_high_power_ = false;
}
}
#endif
float adjusted_value = (state * (this->max_power_ - this->min_power_)) + this->min_power_;
if (this->is_inverted())
adjusted_value = 1.0f - adjusted_value;
this->write_state(adjusted_value);
}
void FloatOutput::write_state(bool state) { this->set_level(state != this->inverted_ ? 1.0f : 0.0f); }
} // namespace output
} // namespace esphome
+71
View File
@@ -0,0 +1,71 @@
#pragma once
#include "esphome/core/component.h"
#include "binary_output.h"
namespace esphome {
namespace output {
#define LOG_FLOAT_OUTPUT(this) \
LOG_BINARY_OUTPUT(this) \
if (this->max_power_ != 1.0f) { \
ESP_LOGCONFIG(TAG, " Max Power: %.1f%%", this->max_power_ * 100.0f); \
} \
if (this->min_power_ != 0.0f) { \
ESP_LOGCONFIG(TAG, " Min Power: %.1f%%", this->min_power_ * 100.0f); \
}
/** Base class for all output components that can output a variable level, like PWM.
*
* Floating Point Outputs always use output values in the range from 0.0 to 1.0 (inclusive), where 0.0 means off
* and 1.0 means fully on. While using floating point numbers might make computation slower, it
* makes using maths much easier and (in theory) supports all possible bit depths.
*
* If you want to create a FloatOutput yourself, you essentially just have to override write_state(float).
* That method will be called for you with inversion and max-min power and offset to min power already applied.
*
* This interface is compatible with BinaryOutput (and will automatically convert the binary states to floating
* point states for you). Additionally, this class provides a way for users to set a minimum and/or maximum power
* output
*/
class FloatOutput : public BinaryOutput {
public:
/** Set the maximum power output of this component.
*
* All values are multiplied by max_power - min_power and offset to min_power to get the adjusted value.
*
* @param max_power Automatically clamped from 0 or min_power to 1.
*/
void set_max_power(float max_power);
/** Set the minimum power output of this component.
*
* All values are multiplied by max_power - min_power and offset by min_power to get the adjusted value.
*
* @param min_power Automatically clamped from 0 to max_power or 1.
*/
void set_min_power(float min_power);
/// Set the level of this float output, this is called from the front-end.
void set_level(float state);
// ========== INTERNAL METHODS ==========
// (In most use cases you won't need these)
/// Get the maximum power output.
float get_max_power() const;
/// Get the minimum power output.
float get_min_power() const;
protected:
/// Implement BinarySensor's write_enabled; this should never be called.
void write_state(bool state) override;
virtual void write_state(float state) = 0;
float max_power_{1.0f};
float min_power_{0.0f};
};
} // namespace output
} // namespace esphome
-28
View File
@@ -1,28 +0,0 @@
import voluptuous as vol
from esphome import pins
from esphome.components import output
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_PIN
from esphome.cpp_generator import Pvariable
from esphome.cpp_helpers import gpio_output_pin_expression, setup_component
from esphome.cpp_types import App, Component
GPIOBinaryOutputComponent = output.output_ns.class_('GPIOBinaryOutputComponent',
output.BinaryOutput, Component)
PLATFORM_SCHEMA = output.BINARY_OUTPUT_PLATFORM_SCHEMA.extend({
vol.Required(CONF_ID): cv.declare_variable_id(GPIOBinaryOutputComponent),
vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
}).extend(cv.COMPONENT_SCHEMA.schema)
def to_code(config):
pin = yield gpio_output_pin_expression(config[CONF_PIN])
rhs = App.make_gpio_output(pin)
gpio = Pvariable(config[CONF_ID], rhs)
output.setup_output_platform(gpio, config)
setup_component(gpio, config)
BUILD_FLAGS = '-DUSE_GPIO_OUTPUT'
-47
View File
@@ -1,47 +0,0 @@
import voluptuous as vol
from esphome import pins
from esphome.components import output
import esphome.config_validation as cv
from esphome.const import APB_CLOCK_FREQ, CONF_BIT_DEPTH, CONF_CHANNEL, CONF_FREQUENCY, \
CONF_ID, CONF_PIN, ESP_PLATFORM_ESP32
from esphome.cpp_generator import Pvariable, add
from esphome.cpp_helpers import setup_component
from esphome.cpp_types import App, Component
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
def validate_frequency_bit_depth(obj):
frequency = obj.get(CONF_FREQUENCY, 1000)
bit_depth = obj.get(CONF_BIT_DEPTH, 12)
max_freq = APB_CLOCK_FREQ / (2**bit_depth)
if frequency > max_freq:
raise vol.Invalid('Maximum frequency for bit depth {} is {}Hz'.format(bit_depth, max_freq))
return obj
LEDCOutputComponent = output.output_ns.class_('LEDCOutputComponent', output.FloatOutput, Component)
PLATFORM_SCHEMA = vol.All(output.FLOAT_OUTPUT_PLATFORM_SCHEMA.extend({
vol.Required(CONF_ID): cv.declare_variable_id(LEDCOutputComponent),
vol.Required(CONF_PIN): pins.output_pin,
vol.Optional(CONF_FREQUENCY): cv.frequency,
vol.Optional(CONF_BIT_DEPTH): vol.All(vol.Coerce(int), vol.Range(min=1, max=15)),
vol.Optional(CONF_CHANNEL): vol.All(vol.Coerce(int), vol.Range(min=0, max=15))
}).extend(cv.COMPONENT_SCHEMA.schema), validate_frequency_bit_depth)
def to_code(config):
frequency = config.get(CONF_FREQUENCY)
if frequency is None and CONF_BIT_DEPTH in config:
frequency = 1000
rhs = App.make_ledc_output(config[CONF_PIN], frequency, config.get(CONF_BIT_DEPTH))
ledc = Pvariable(config[CONF_ID], rhs)
if CONF_CHANNEL in config:
add(ledc.set_channel(config[CONF_CHANNEL]))
output.setup_output_platform(ledc, config)
setup_component(ledc, config)
BUILD_FLAGS = '-DUSE_LEDC_OUTPUT'
-33
View File
@@ -1,33 +0,0 @@
import voluptuous as vol
from esphome.components import output
from esphome.components.my9231 import MY9231OutputComponent
import esphome.config_validation as cv
from esphome.const import CONF_CHANNEL, CONF_ID, CONF_MY9231_ID, CONF_POWER_SUPPLY
from esphome.cpp_generator import Pvariable, get_variable
from esphome.cpp_helpers import setup_component
DEPENDENCIES = ['my9231']
Channel = MY9231OutputComponent.class_('Channel', output.FloatOutput)
PLATFORM_SCHEMA = output.FLOAT_OUTPUT_PLATFORM_SCHEMA.extend({
vol.Required(CONF_ID): cv.declare_variable_id(Channel),
vol.Required(CONF_CHANNEL): vol.All(vol.Coerce(int),
vol.Range(min=0, max=65535)),
cv.GenerateID(CONF_MY9231_ID): cv.use_variable_id(MY9231OutputComponent),
}).extend(cv.COMPONENT_SCHEMA.schema)
def to_code(config):
power_supply = None
if CONF_POWER_SUPPLY in config:
power_supply = yield get_variable(config[CONF_POWER_SUPPLY])
my9231 = yield get_variable(config[CONF_MY9231_ID])
rhs = my9231.create_channel(config[CONF_CHANNEL], power_supply)
out = Pvariable(config[CONF_ID], rhs)
output.setup_output_platform(out, config, skip_power_supply=True)
setup_component(out, config)
BUILD_FLAGS = '-DUSE_MY9231_OUTPUT'
-31
View File
@@ -1,31 +0,0 @@
import voluptuous as vol
from esphome.components import output
from esphome.components.pca9685 import PCA9685OutputComponent
import esphome.config_validation as cv
from esphome.const import CONF_CHANNEL, CONF_ID, CONF_PCA9685_ID, CONF_POWER_SUPPLY
from esphome.cpp_generator import Pvariable, get_variable
DEPENDENCIES = ['pca9685']
Channel = PCA9685OutputComponent.class_('Channel', output.FloatOutput)
PLATFORM_SCHEMA = output.FLOAT_OUTPUT_PLATFORM_SCHEMA.extend({
vol.Required(CONF_ID): cv.declare_variable_id(Channel),
vol.Required(CONF_CHANNEL): vol.All(vol.Coerce(int),
vol.Range(min=0, max=15)),
cv.GenerateID(CONF_PCA9685_ID): cv.use_variable_id(PCA9685OutputComponent),
})
def to_code(config):
power_supply = None
if CONF_POWER_SUPPLY in config:
power_supply = yield get_variable(config[CONF_POWER_SUPPLY])
pca9685 = yield get_variable(config[CONF_PCA9685_ID])
rhs = pca9685.create_channel(config[CONF_CHANNEL], power_supply)
out = Pvariable(config[CONF_ID], rhs)
output.setup_output_platform(out, config, skip_power_supply=True)
BUILD_FLAGS = '-DUSE_PCA9685_OUTPUT'
@@ -0,0 +1,19 @@
from esphome.components import output, switch
import esphome.config_validation as cv
import esphome.codegen as cg
from esphome.const import CONF_ID, CONF_NAME, CONF_OUTPUT
from .. import output_ns
OutputSwitch = output_ns.class_('OutputSwitch', switch.Switch, cg.Component)
CONFIG_SCHEMA = cv.nameable(switch.SWITCH_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(OutputSwitch),
cv.Required(CONF_OUTPUT): cv.use_variable_id(output.BinaryOutput),
}).extend(cv.COMPONENT_SCHEMA))
def to_code(config):
output_ = yield cg.get_variable(config[CONF_OUTPUT])
var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME], output_)
yield cg.register_component(var, config)
yield switch.register_switch(var, config)
@@ -0,0 +1,31 @@
#include "output_switch.h"
#include "esphome/core/log.h"
namespace esphome {
namespace output {
static const char *TAG = "output.switch";
void OutputSwitch::dump_config() { LOG_SWITCH("", "Output Switch", this); }
void OutputSwitch::setup() {
auto restored = this->get_initial_state();
if (!restored.has_value())
return;
if (*restored) {
this->turn_on();
} else {
this->turn_off();
}
}
void OutputSwitch::write_state(bool state) {
if (state) {
this->output_->turn_on();
} else {
this->output_->turn_off();
}
this->publish_state(state);
}
} // namespace output
} // namespace esphome
@@ -0,0 +1,25 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/switch/switch.h"
#include "esphome/components/output/binary_output.h"
namespace esphome {
namespace output {
class OutputSwitch : public switch_::Switch, public Component {
public:
OutputSwitch(const std::string &name, BinaryOutput *output) : Switch(name), output_(output) {}
void setup() override;
float get_setup_priority() const override { return setup_priority::HARDWARE; }
void dump_config() override;
protected:
void write_state(bool state) override;
output::BinaryOutput *output_;
};
} // namespace output
} // namespace esphome