mirror of
https://github.com/esphome/esphome.git
synced 2025-10-04 02:52:22 +01:00
🏗 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:
@@ -1,125 +1,117 @@
|
||||
import voluptuous as vol
|
||||
|
||||
from esphome.automation import ACTION_REGISTRY, maybe_simple_id
|
||||
from esphome.components import mqtt
|
||||
from esphome.components.mqtt import setup_mqtt_component
|
||||
import esphome.config_validation as cv
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import mqtt
|
||||
from esphome.const import CONF_ID, CONF_INTERNAL, CONF_MQTT_ID, CONF_OSCILLATING, \
|
||||
CONF_OSCILLATION_COMMAND_TOPIC, CONF_OSCILLATION_STATE_TOPIC, CONF_SPEED, \
|
||||
CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_STATE_TOPIC
|
||||
from esphome.core import CORE
|
||||
from esphome.cpp_generator import Pvariable, add, get_variable, templatable
|
||||
from esphome.cpp_types import Action, Application, Component, Nameable, bool_, esphome_ns
|
||||
CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_STATE_TOPIC, CONF_NAME
|
||||
from esphome.core import CORE, coroutine
|
||||
|
||||
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
|
||||
})
|
||||
|
||||
fan_ns = esphome_ns.namespace('fan')
|
||||
FanState = fan_ns.class_('FanState', Nameable, Component)
|
||||
MQTTFanComponent = fan_ns.class_('MQTTFanComponent', mqtt.MQTTComponent)
|
||||
MakeFan = Application.struct('MakeFan')
|
||||
fan_ns = cg.esphome_ns.namespace('fan')
|
||||
FanState = fan_ns.class_('FanState', cg.Nameable, cg.Component)
|
||||
MakeFan = cg.Application.struct('MakeFan')
|
||||
|
||||
# Actions
|
||||
TurnOnAction = fan_ns.class_('TurnOnAction', Action)
|
||||
TurnOffAction = fan_ns.class_('TurnOffAction', Action)
|
||||
ToggleAction = fan_ns.class_('ToggleAction', Action)
|
||||
TurnOnAction = fan_ns.class_('TurnOnAction', cg.Action)
|
||||
TurnOffAction = fan_ns.class_('TurnOffAction', cg.Action)
|
||||
ToggleAction = fan_ns.class_('ToggleAction', cg.Action)
|
||||
|
||||
FanSpeed = fan_ns.enum('FanSpeed')
|
||||
FAN_SPEED_OFF = FanSpeed.FAN_SPEED_OFF
|
||||
FAN_SPEED_LOW = FanSpeed.FAN_SPEED_LOW
|
||||
FAN_SPEED_MEDIUM = FanSpeed.FAN_SPEED_MEDIUM
|
||||
FAN_SPEED_HIGH = FanSpeed.FAN_SPEED_HIGH
|
||||
FAN_SPEEDS = {
|
||||
'OFF': FanSpeed.FAN_SPEED_OFF,
|
||||
'LOW': FanSpeed.FAN_SPEED_LOW,
|
||||
'MEDIuM': FanSpeed.FAN_SPEED_MEDIUM,
|
||||
'HIGH': FanSpeed.FAN_SPEED_HIGH,
|
||||
}
|
||||
|
||||
FAN_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_variable_id(FanState),
|
||||
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTFanComponent),
|
||||
vol.Optional(CONF_OSCILLATION_STATE_TOPIC): vol.All(cv.requires_component('mqtt'),
|
||||
cv.publish_topic),
|
||||
vol.Optional(CONF_OSCILLATION_COMMAND_TOPIC): vol.All(cv.requires_component('mqtt'),
|
||||
cv.subscribe_topic),
|
||||
cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_variable_id(mqtt.MQTTFanComponent),
|
||||
cv.Optional(CONF_OSCILLATION_STATE_TOPIC): cv.All(cv.requires_component('mqtt'),
|
||||
cv.publish_topic),
|
||||
cv.Optional(CONF_OSCILLATION_COMMAND_TOPIC): cv.All(cv.requires_component('mqtt'),
|
||||
cv.subscribe_topic),
|
||||
})
|
||||
|
||||
FAN_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(FAN_SCHEMA.schema)
|
||||
|
||||
FAN_SPEEDS = {
|
||||
'OFF': FAN_SPEED_OFF,
|
||||
'LOW': FAN_SPEED_LOW,
|
||||
'MEDIUM': FAN_SPEED_MEDIUM,
|
||||
'HIGH': FAN_SPEED_HIGH,
|
||||
}
|
||||
|
||||
|
||||
def setup_fan_core_(fan_var, config):
|
||||
@coroutine
|
||||
def setup_fan_core_(var, config):
|
||||
if CONF_INTERNAL in config:
|
||||
add(fan_var.set_internal(config[CONF_INTERNAL]))
|
||||
cg.add(var.set_internal(config[CONF_INTERNAL]))
|
||||
|
||||
mqtt_ = fan_var.Pget_mqtt()
|
||||
if CONF_OSCILLATION_STATE_TOPIC in config:
|
||||
add(mqtt_.set_custom_oscillation_state_topic(config[CONF_OSCILLATION_STATE_TOPIC]))
|
||||
if CONF_OSCILLATION_COMMAND_TOPIC in config:
|
||||
add(mqtt_.set_custom_oscillation_command_topic(config[CONF_OSCILLATION_COMMAND_TOPIC]))
|
||||
if CONF_SPEED_STATE_TOPIC in config:
|
||||
add(mqtt_.set_custom_speed_state_topic(config[CONF_SPEED_STATE_TOPIC]))
|
||||
if CONF_SPEED_COMMAND_TOPIC in config:
|
||||
add(mqtt_.set_custom_speed_command_topic(config[CONF_SPEED_COMMAND_TOPIC]))
|
||||
setup_mqtt_component(mqtt_, config)
|
||||
if CONF_MQTT_ID in config:
|
||||
mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var)
|
||||
yield mqtt.register_mqtt_component(mqtt_, config)
|
||||
|
||||
if CONF_OSCILLATION_STATE_TOPIC in config:
|
||||
cg.add(mqtt_.set_custom_oscillation_state_topic(config[CONF_OSCILLATION_STATE_TOPIC]))
|
||||
if CONF_OSCILLATION_COMMAND_TOPIC in config:
|
||||
cg.add(mqtt_.set_custom_oscillation_command_topic(
|
||||
config[CONF_OSCILLATION_COMMAND_TOPIC]))
|
||||
if CONF_SPEED_STATE_TOPIC in config:
|
||||
cg.add(mqtt_.set_custom_speed_state_topic(config[CONF_SPEED_STATE_TOPIC]))
|
||||
if CONF_SPEED_COMMAND_TOPIC in config:
|
||||
cg.add(mqtt_.set_custom_speed_command_topic(config[CONF_SPEED_COMMAND_TOPIC]))
|
||||
|
||||
|
||||
def setup_fan(fan_obj, config):
|
||||
fan_var = Pvariable(config[CONF_ID], fan_obj, has_side_effects=False)
|
||||
CORE.add_job(setup_fan_core_, fan_var, config)
|
||||
@coroutine
|
||||
def register_fan(var, config):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
cg.add(cg.App.register_fan(var))
|
||||
yield setup_fan_core_(var, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_FAN'
|
||||
@coroutine
|
||||
def create_fan_state(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME])
|
||||
yield register_fan(var, config)
|
||||
yield var
|
||||
|
||||
CONF_FAN_TOGGLE = 'fan.toggle'
|
||||
FAN_TOGGLE_ACTION_SCHEMA = maybe_simple_id({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(FanState),
|
||||
|
||||
FAN_ACTION_SCHEMA = maybe_simple_id({
|
||||
cv.Required(CONF_ID): cv.use_variable_id(FanState),
|
||||
})
|
||||
|
||||
|
||||
@ACTION_REGISTRY.register(CONF_FAN_TOGGLE, FAN_TOGGLE_ACTION_SCHEMA)
|
||||
@ACTION_REGISTRY.register('fan.toggle', FAN_ACTION_SCHEMA)
|
||||
def fan_toggle_to_code(config, action_id, template_arg, args):
|
||||
var = yield get_variable(config[CONF_ID])
|
||||
rhs = var.make_toggle_action(template_arg)
|
||||
var = yield cg.get_variable(config[CONF_ID])
|
||||
type = ToggleAction.template(template_arg)
|
||||
yield Pvariable(action_id, rhs, type=type)
|
||||
rhs = type.new(var)
|
||||
yield cg.Pvariable(action_id, rhs, type=type)
|
||||
|
||||
|
||||
CONF_FAN_TURN_OFF = 'fan.turn_off'
|
||||
FAN_TURN_OFF_ACTION_SCHEMA = maybe_simple_id({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(FanState),
|
||||
})
|
||||
|
||||
|
||||
@ACTION_REGISTRY.register(CONF_FAN_TURN_OFF, FAN_TURN_OFF_ACTION_SCHEMA)
|
||||
@ACTION_REGISTRY.register('fan.turn_off', FAN_ACTION_SCHEMA)
|
||||
def fan_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_FAN_TURN_ON = 'fan.turn_on'
|
||||
FAN_TURN_ON_ACTION_SCHEMA = maybe_simple_id({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(FanState),
|
||||
vol.Optional(CONF_OSCILLATING): cv.templatable(cv.boolean),
|
||||
vol.Optional(CONF_SPEED): cv.templatable(cv.one_of(*FAN_SPEEDS, upper=True)),
|
||||
})
|
||||
|
||||
|
||||
@ACTION_REGISTRY.register(CONF_FAN_TURN_ON, FAN_TURN_ON_ACTION_SCHEMA)
|
||||
@ACTION_REGISTRY.register('fan.turn_on', maybe_simple_id({
|
||||
cv.Required(CONF_ID): cv.use_variable_id(FanState),
|
||||
cv.Optional(CONF_OSCILLATING): cv.templatable(cv.boolean),
|
||||
cv.Optional(CONF_SPEED): cv.templatable(cv.one_of(*FAN_SPEEDS, upper=True)),
|
||||
}))
|
||||
def fan_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)
|
||||
action = Pvariable(action_id, rhs, type=type)
|
||||
rhs = type.new(var)
|
||||
action = cg.Pvariable(action_id, rhs, type=type)
|
||||
if CONF_OSCILLATING in config:
|
||||
template_ = yield templatable(config[CONF_OSCILLATING], args, bool_)
|
||||
add(action.set_oscillating(template_))
|
||||
template_ = yield cg.templatable(config[CONF_OSCILLATING], args, bool)
|
||||
cg.add(action.set_oscillating(template_))
|
||||
if CONF_SPEED in config:
|
||||
template_ = yield templatable(config[CONF_SPEED], args, FanSpeed,
|
||||
to_exp=FAN_SPEEDS)
|
||||
add(action.set_speed(template_))
|
||||
template_ = yield cg.templatable(config[CONF_SPEED], args, FanSpeed,
|
||||
to_exp=FAN_SPEEDS)
|
||||
cg.add(action.set_speed(template_))
|
||||
yield action
|
||||
|
||||
|
||||
def to_code(config):
|
||||
cg.add_define('USE_FAN')
|
||||
cg.add_global(fan_ns.using)
|
||||
|
10
esphome/components/fan/automation.cpp
Normal file
10
esphome/components/fan/automation.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include "automation.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace fan {
|
||||
|
||||
static const char *TAG = "fan.automation";
|
||||
|
||||
} // namespace fan
|
||||
} // namespace esphome
|
60
esphome/components/fan/automation.h
Normal file
60
esphome/components/fan/automation.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "fan_state.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace fan {
|
||||
|
||||
template<typename... Ts> class TurnOnAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit TurnOnAction(FanState *state) : state_(state) {}
|
||||
|
||||
TEMPLATABLE_VALUE(bool, oscillating)
|
||||
TEMPLATABLE_VALUE(FanSpeed, speed)
|
||||
|
||||
void play(Ts... x) override {
|
||||
auto call = this->state_->turn_on();
|
||||
if (this->oscillating_.has_value()) {
|
||||
call.set_oscillating(this->oscillating_.value(x...));
|
||||
}
|
||||
if (this->speed_.has_value()) {
|
||||
call.set_speed(this->speed_.value(x...));
|
||||
}
|
||||
call.perform();
|
||||
this->play_next(x...);
|
||||
}
|
||||
|
||||
protected:
|
||||
FanState *state_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class TurnOffAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit TurnOffAction(FanState *state) : state_(state) {}
|
||||
|
||||
void play(Ts... x) override {
|
||||
this->state_->turn_off().perform();
|
||||
this->play_next(x...);
|
||||
}
|
||||
|
||||
protected:
|
||||
FanState *state_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class ToggleAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit ToggleAction(FanState *state) : state_(state) {}
|
||||
|
||||
void play(Ts... x) override {
|
||||
this->state_->toggle().perform();
|
||||
this->play_next(x...);
|
||||
}
|
||||
|
||||
protected:
|
||||
FanState *state_;
|
||||
};
|
||||
|
||||
} // namespace fan
|
||||
} // namespace esphome
|
@@ -1,28 +0,0 @@
|
||||
import voluptuous as vol
|
||||
|
||||
from esphome.components import fan, output
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_MAKE_ID, CONF_NAME, CONF_OSCILLATION_OUTPUT, CONF_OUTPUT
|
||||
from esphome.cpp_generator import add, get_variable, variable
|
||||
from esphome.cpp_helpers import setup_component
|
||||
from esphome.cpp_types import App
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(fan.FAN_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(fan.MakeFan),
|
||||
vol.Required(CONF_OUTPUT): cv.use_variable_id(output.BinaryOutput),
|
||||
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.use_variable_id(output.BinaryOutput),
|
||||
}).extend(cv.COMPONENT_SCHEMA.schema))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
output_ = yield get_variable(config[CONF_OUTPUT])
|
||||
|
||||
rhs = App.make_fan(config[CONF_NAME])
|
||||
fan_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||
add(fan_struct.Poutput.set_binary(output_))
|
||||
if CONF_OSCILLATION_OUTPUT in config:
|
||||
oscillation_output = yield get_variable(config[CONF_OSCILLATION_OUTPUT])
|
||||
add(fan_struct.Poutput.set_oscillation(oscillation_output))
|
||||
|
||||
fan.setup_fan(fan_struct.Pstate, config)
|
||||
setup_component(fan_struct.Poutput, config)
|
107
esphome/components/fan/fan_state.cpp
Normal file
107
esphome/components/fan/fan_state.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "fan_state.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace fan {
|
||||
|
||||
static const char *TAG = "fan";
|
||||
|
||||
const FanTraits &FanState::get_traits() const { return this->traits_; }
|
||||
void FanState::set_traits(const FanTraits &traits) { this->traits_ = traits; }
|
||||
void FanState::add_on_state_callback(std::function<void()> &&callback) {
|
||||
this->state_callback_.add(std::move(callback));
|
||||
}
|
||||
FanState::FanState(const std::string &name) : Nameable(name) {}
|
||||
|
||||
FanState::StateCall FanState::turn_on() { return this->make_call().set_state(true); }
|
||||
FanState::StateCall FanState::turn_off() { return this->make_call().set_state(false); }
|
||||
FanState::StateCall FanState::toggle() { return this->make_call().set_state(!this->state); }
|
||||
FanState::StateCall FanState::make_call() { return FanState::StateCall(this); }
|
||||
|
||||
struct FanStateRTCState {
|
||||
bool state;
|
||||
FanSpeed speed;
|
||||
bool oscillating;
|
||||
};
|
||||
|
||||
void FanState::setup() {
|
||||
this->rtc_ = global_preferences.make_preference<FanStateRTCState>(this->get_object_id_hash());
|
||||
FanStateRTCState recovered{};
|
||||
if (!this->rtc_.load(&recovered))
|
||||
return;
|
||||
|
||||
auto call = this->make_call();
|
||||
call.set_state(recovered.state);
|
||||
call.set_speed(recovered.speed);
|
||||
call.set_oscillating(recovered.oscillating);
|
||||
call.perform();
|
||||
}
|
||||
float FanState::get_setup_priority() const { return setup_priority::HARDWARE - 1.0f; }
|
||||
uint32_t FanState::hash_base() { return 418001110UL; }
|
||||
|
||||
FanState::StateCall::StateCall(FanState *state) : state_(state) {}
|
||||
FanState::StateCall &FanState::StateCall::set_state(bool state) {
|
||||
this->binary_state_ = state;
|
||||
return *this;
|
||||
}
|
||||
FanState::StateCall &FanState::StateCall::set_state(optional<bool> state) {
|
||||
this->binary_state_ = state;
|
||||
return *this;
|
||||
}
|
||||
FanState::StateCall &FanState::StateCall::set_oscillating(bool oscillating) {
|
||||
this->oscillating_ = oscillating;
|
||||
return *this;
|
||||
}
|
||||
FanState::StateCall &FanState::StateCall::set_oscillating(optional<bool> oscillating) {
|
||||
this->oscillating_ = oscillating;
|
||||
return *this;
|
||||
}
|
||||
FanState::StateCall &FanState::StateCall::set_speed(FanSpeed speed) {
|
||||
this->speed_ = speed;
|
||||
return *this;
|
||||
}
|
||||
FanState::StateCall &FanState::StateCall::set_speed(optional<FanSpeed> speed) {
|
||||
this->speed_ = speed;
|
||||
return *this;
|
||||
}
|
||||
void FanState::StateCall::perform() const {
|
||||
if (this->binary_state_.has_value()) {
|
||||
this->state_->state = *this->binary_state_;
|
||||
}
|
||||
if (this->oscillating_.has_value()) {
|
||||
this->state_->oscillating = *this->oscillating_;
|
||||
}
|
||||
if (this->speed_.has_value()) {
|
||||
switch (*this->speed_) {
|
||||
case FAN_SPEED_LOW:
|
||||
case FAN_SPEED_MEDIUM:
|
||||
case FAN_SPEED_HIGH:
|
||||
this->state_->speed = *this->speed_;
|
||||
break;
|
||||
default:
|
||||
// protect from invalid input
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FanStateRTCState saved{};
|
||||
saved.state = this->state_->state;
|
||||
saved.speed = this->state_->speed;
|
||||
saved.oscillating = this->state_->oscillating;
|
||||
this->state_->rtc_.save(&saved);
|
||||
|
||||
this->state_->state_callback_.call();
|
||||
}
|
||||
FanState::StateCall &FanState::StateCall::set_speed(const char *speed) {
|
||||
if (strcasecmp(speed, "low") == 0) {
|
||||
this->set_speed(FAN_SPEED_LOW);
|
||||
} else if (strcasecmp(speed, "medium") == 0) {
|
||||
this->set_speed(FAN_SPEED_MEDIUM);
|
||||
} else if (strcasecmp(speed, "high") == 0) {
|
||||
this->set_speed(FAN_SPEED_HIGH);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace fan
|
||||
} // namespace esphome
|
76
esphome/components/fan/fan_state.h
Normal file
76
esphome/components/fan/fan_state.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/preferences.h"
|
||||
#include "fan_traits.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace fan {
|
||||
|
||||
/// Simple enum to represent the speed of a fan.
|
||||
enum FanSpeed {
|
||||
FAN_SPEED_LOW = 0, ///< The fan is running on low speed.
|
||||
FAN_SPEED_MEDIUM = 1, ///< The fan is running on medium speed.
|
||||
FAN_SPEED_HIGH = 2 ///< The fan is running on high/full speed.
|
||||
};
|
||||
|
||||
class FanState : public Nameable, public Component {
|
||||
public:
|
||||
/// Construct the fan state with name.
|
||||
explicit FanState(const std::string &name);
|
||||
|
||||
/// Register a callback that will be called each time the state changes.
|
||||
void add_on_state_callback(std::function<void()> &&callback);
|
||||
|
||||
/// Get the traits of this fan (i.e. what features it supports).
|
||||
const FanTraits &get_traits() const;
|
||||
/// Set the traits of this fan (i.e. what features it supports).
|
||||
void set_traits(const FanTraits &traits);
|
||||
|
||||
/// The current ON/OFF state of the fan.
|
||||
bool state{false};
|
||||
/// The current oscillation state of the fan.
|
||||
bool oscillating{false};
|
||||
/// The current fan speed.
|
||||
FanSpeed speed{FAN_SPEED_HIGH};
|
||||
|
||||
class StateCall {
|
||||
public:
|
||||
explicit StateCall(FanState *state);
|
||||
|
||||
FanState::StateCall &set_state(bool state);
|
||||
FanState::StateCall &set_state(optional<bool> state);
|
||||
FanState::StateCall &set_oscillating(bool oscillating);
|
||||
FanState::StateCall &set_oscillating(optional<bool> oscillating);
|
||||
FanState::StateCall &set_speed(FanSpeed speed);
|
||||
FanState::StateCall &set_speed(optional<FanSpeed> speed);
|
||||
FanState::StateCall &set_speed(const char *speed);
|
||||
|
||||
void perform() const;
|
||||
|
||||
protected:
|
||||
FanState *const state_;
|
||||
optional<bool> binary_state_;
|
||||
optional<bool> oscillating_{};
|
||||
optional<FanSpeed> speed_{};
|
||||
};
|
||||
|
||||
FanState::StateCall turn_on();
|
||||
FanState::StateCall turn_off();
|
||||
FanState::StateCall toggle();
|
||||
FanState::StateCall make_call();
|
||||
|
||||
void setup() override;
|
||||
float get_setup_priority() const override;
|
||||
|
||||
protected:
|
||||
uint32_t hash_base() override;
|
||||
|
||||
FanTraits traits_{};
|
||||
CallbackManager<void()> state_callback_{};
|
||||
ESPPreferenceObject rtc_;
|
||||
};
|
||||
|
||||
} // namespace fan
|
||||
} // namespace esphome
|
26
esphome/components/fan/fan_traits.h
Normal file
26
esphome/components/fan/fan_traits.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
namespace esphome {
|
||||
namespace fan {
|
||||
|
||||
class FanTraits {
|
||||
public:
|
||||
FanTraits() = default;
|
||||
FanTraits(bool oscillation, bool speed) : oscillation_(false), speed_(speed) {}
|
||||
|
||||
/// Return if this fan supports oscillation.
|
||||
bool supports_oscillation() const { return this->oscillation_; }
|
||||
/// Set whether this fan supports oscillation.
|
||||
void set_oscillation(bool oscillation) { this->oscillation_ = oscillation; }
|
||||
/// Return if this fan supports speed modes.
|
||||
bool supports_speed() const { return this->speed_; }
|
||||
/// Set whether this fan supports speed modes.
|
||||
void set_speed(bool speed) { this->speed_ = speed; }
|
||||
|
||||
protected:
|
||||
bool oscillation_{false};
|
||||
bool speed_{false};
|
||||
};
|
||||
|
||||
} // namespace fan
|
||||
} // namespace esphome
|
@@ -1,42 +0,0 @@
|
||||
import voluptuous as vol
|
||||
|
||||
from esphome.components import fan, output
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_HIGH, CONF_LOW, CONF_MAKE_ID, CONF_MEDIUM, CONF_NAME, \
|
||||
CONF_OSCILLATION_OUTPUT, CONF_OUTPUT, CONF_SPEED, CONF_SPEED_COMMAND_TOPIC, \
|
||||
CONF_SPEED_STATE_TOPIC
|
||||
from esphome.cpp_generator import add, get_variable, variable
|
||||
from esphome.cpp_types import App
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(fan.FAN_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(fan.MakeFan),
|
||||
vol.Required(CONF_OUTPUT): cv.use_variable_id(output.FloatOutput),
|
||||
vol.Optional(CONF_SPEED_STATE_TOPIC): cv.publish_topic,
|
||||
vol.Optional(CONF_SPEED_COMMAND_TOPIC): cv.subscribe_topic,
|
||||
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.use_variable_id(output.BinaryOutput),
|
||||
vol.Optional(CONF_SPEED): cv.Schema({
|
||||
vol.Required(CONF_LOW): cv.percentage,
|
||||
vol.Required(CONF_MEDIUM): cv.percentage,
|
||||
vol.Required(CONF_HIGH): cv.percentage,
|
||||
}),
|
||||
}).extend(cv.COMPONENT_SCHEMA.schema))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
output_ = yield get_variable(config[CONF_OUTPUT])
|
||||
rhs = App.make_fan(config[CONF_NAME])
|
||||
fan_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||
if CONF_SPEED in config:
|
||||
speeds = config[CONF_SPEED]
|
||||
add(fan_struct.Poutput.set_speed(output_,
|
||||
speeds[CONF_LOW],
|
||||
speeds[CONF_MEDIUM],
|
||||
speeds[CONF_HIGH]))
|
||||
else:
|
||||
add(fan_struct.Poutput.set_speed(output_))
|
||||
|
||||
if CONF_OSCILLATION_OUTPUT in config:
|
||||
oscillation_output = yield get_variable(config[CONF_OSCILLATION_OUTPUT])
|
||||
add(fan_struct.Poutput.set_oscillation(oscillation_output))
|
||||
|
||||
fan.setup_fan(fan_struct.Pstate, config)
|
Reference in New Issue
Block a user