mirror of
https://github.com/esphome/esphome.git
synced 2026-01-23 11:29:12 -07:00
Compare commits
10 Commits
compact_st
...
copilot/up
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c0e0b8d76 | ||
|
|
48b80858a7 | ||
|
|
081081f69a | ||
|
|
8abb783b64 | ||
|
|
bccfe9eead | ||
|
|
35fb44da36 | ||
|
|
1dfb8926d3 | ||
|
|
0d63c755b7 | ||
|
|
6f2ca4c2a7 | ||
|
|
cfb61bc50a |
@@ -1,3 +1,5 @@
|
||||
import logging
|
||||
|
||||
from esphome import automation
|
||||
from esphome.automation import Condition, maybe_simple_id
|
||||
import esphome.codegen as cg
|
||||
@@ -9,6 +11,7 @@ from esphome.const import (
|
||||
CONF_ICON,
|
||||
CONF_ID,
|
||||
CONF_MQTT_ID,
|
||||
CONF_ON_IDLE,
|
||||
CONF_ON_OPEN,
|
||||
CONF_POSITION,
|
||||
CONF_POSITION_COMMAND_TOPIC,
|
||||
@@ -53,6 +56,8 @@ DEVICE_CLASSES = [
|
||||
DEVICE_CLASS_WINDOW,
|
||||
]
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
cover_ns = cg.esphome_ns.namespace("cover")
|
||||
|
||||
Cover = cover_ns.class_("Cover", cg.EntityBase)
|
||||
@@ -83,14 +88,30 @@ ControlAction = cover_ns.class_("ControlAction", automation.Action)
|
||||
CoverPublishAction = cover_ns.class_("CoverPublishAction", automation.Action)
|
||||
CoverIsOpenCondition = cover_ns.class_("CoverIsOpenCondition", Condition)
|
||||
CoverIsClosedCondition = cover_ns.class_("CoverIsClosedCondition", Condition)
|
||||
|
||||
# Triggers
|
||||
CoverOpenTrigger = cover_ns.class_("CoverOpenTrigger", automation.Trigger.template())
|
||||
CoverOpenedTrigger = cover_ns.class_(
|
||||
"CoverOpenedTrigger", automation.Trigger.template()
|
||||
)
|
||||
CoverClosedTrigger = cover_ns.class_(
|
||||
"CoverClosedTrigger", automation.Trigger.template()
|
||||
)
|
||||
CoverTrigger = cover_ns.class_("CoverTrigger", automation.Trigger.template())
|
||||
|
||||
# Cover-specific constants
|
||||
CONF_ON_CLOSED = "on_closed"
|
||||
CONF_ON_OPENED = "on_opened"
|
||||
CONF_ON_OPENING = "on_opening"
|
||||
CONF_ON_CLOSING = "on_closing"
|
||||
|
||||
OPERATIONS = (
|
||||
CONF_ON_CLOSING,
|
||||
CONF_ON_OPENING,
|
||||
CONF_ON_IDLE,
|
||||
)
|
||||
|
||||
|
||||
def get_operation_from_conf_(conf: str) -> CoverOperation:
|
||||
return getattr(CoverOperation, "COVER_OPERATION_" + conf.split("_")[1].upper())
|
||||
|
||||
|
||||
_COVER_SCHEMA = (
|
||||
cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
|
||||
@@ -111,9 +132,15 @@ _COVER_SCHEMA = (
|
||||
cv.Optional(CONF_TILT_STATE_TOPIC): cv.All(
|
||||
cv.requires_component("mqtt"), cv.subscribe_topic
|
||||
),
|
||||
# Deprecated trigger
|
||||
cv.Optional(CONF_ON_OPEN): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CoverOpenTrigger),
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CoverOpenedTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_OPENED): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CoverOpenedTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_CLOSED): automation.validate_automation(
|
||||
@@ -121,6 +148,16 @@ _COVER_SCHEMA = (
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CoverClosedTrigger),
|
||||
}
|
||||
),
|
||||
**{
|
||||
cv.Optional(conf): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||
CoverTrigger.template(get_operation_from_conf_(conf))
|
||||
),
|
||||
}
|
||||
)
|
||||
for conf in OPERATIONS
|
||||
},
|
||||
}
|
||||
)
|
||||
)
|
||||
@@ -157,12 +194,23 @@ async def setup_cover_core_(var, config):
|
||||
if (device_class := config.get(CONF_DEVICE_CLASS)) is not None:
|
||||
cg.add(var.set_device_class(device_class))
|
||||
|
||||
for conf in config.get(CONF_ON_OPEN, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
for conf in config.get(CONF_ON_CLOSED, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
if on_opens := config.get(CONF_ON_OPEN):
|
||||
_LOGGER.warning(
|
||||
"The 'on_open' trigger for covers is deprecated and will be removed in a future release. Please use 'on_opened' instead."
|
||||
)
|
||||
for conf in on_opens:
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
for on_op in OPERATIONS:
|
||||
if triggers := config.get(on_op):
|
||||
for conf in triggers:
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
for on_state in [CONF_ON_OPENED, CONF_ON_CLOSED]:
|
||||
if triggers := config.get(on_state):
|
||||
for conf in triggers:
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
|
||||
if (mqtt_id := config.get(CONF_MQTT_ID)) is not None:
|
||||
mqtt_ = cg.new_Pvariable(mqtt_id, var)
|
||||
@@ -258,6 +306,26 @@ async def cover_control_to_code(config, action_id, template_arg, args):
|
||||
return var
|
||||
|
||||
|
||||
@automation.register_condition(
|
||||
"cover.is_open",
|
||||
CoverIsOpenCondition,
|
||||
cv.maybe_simple_value({cv.Required(CONF_ID): cv.use_id(Cover)}, key=CONF_ID),
|
||||
)
|
||||
async def cover_is_open_to_code(config, condition_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(condition_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_condition(
|
||||
"cover.is_closed",
|
||||
CoverIsClosedCondition,
|
||||
cv.maybe_simple_value({cv.Required(CONF_ID): cv.use_id(Cover)}, key=CONF_ID),
|
||||
)
|
||||
async def cover_is_closed_to_code(config, condition_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(condition_id, template_arg, paren)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.CORE)
|
||||
async def to_code(config):
|
||||
cg.add_global(cover_ns.using)
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "cover.h"
|
||||
|
||||
namespace esphome::cover {
|
||||
|
||||
template<typename... Ts> class OpenAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit OpenAction(Cover *cover) : cover_(cover) {}
|
||||
@@ -72,6 +71,7 @@ template<typename... Ts> class ControlAction : public Action<Ts...> {
|
||||
template<typename... Ts> class CoverPublishAction : public Action<Ts...> {
|
||||
public:
|
||||
CoverPublishAction(Cover *cover) : cover_(cover) {}
|
||||
|
||||
TEMPLATABLE_VALUE(float, position)
|
||||
TEMPLATABLE_VALUE(float, tilt)
|
||||
TEMPLATABLE_VALUE(CoverOperation, current_operation)
|
||||
@@ -93,7 +93,8 @@ template<typename... Ts> class CoverPublishAction : public Action<Ts...> {
|
||||
template<typename... Ts> class CoverIsOpenCondition : public Condition<Ts...> {
|
||||
public:
|
||||
CoverIsOpenCondition(Cover *cover) : cover_(cover) {}
|
||||
bool check(const Ts &...x) override { return this->cover_->is_fully_open(); }
|
||||
|
||||
bool check(const Ts &...x) override { return this->cover_->position == COVER_OPEN; }
|
||||
|
||||
protected:
|
||||
Cover *cover_;
|
||||
@@ -102,32 +103,60 @@ template<typename... Ts> class CoverIsOpenCondition : public Condition<Ts...> {
|
||||
template<typename... Ts> class CoverIsClosedCondition : public Condition<Ts...> {
|
||||
public:
|
||||
CoverIsClosedCondition(Cover *cover) : cover_(cover) {}
|
||||
bool check(const Ts &...x) override { return this->cover_->is_fully_closed(); }
|
||||
|
||||
bool check(const Ts &...x) override { return this->cover_->position == COVER_CLOSED; }
|
||||
|
||||
protected:
|
||||
Cover *cover_;
|
||||
};
|
||||
|
||||
class CoverOpenTrigger : public Trigger<> {
|
||||
class CoverOpenedTrigger : public Trigger<> {
|
||||
public:
|
||||
CoverOpenTrigger(Cover *a_cover) {
|
||||
CoverOpenedTrigger(Cover *a_cover) {
|
||||
a_cover->add_on_state_callback([this, a_cover]() {
|
||||
if (a_cover->is_fully_open()) {
|
||||
this->trigger();
|
||||
if (a_cover->position != this->last_position_) {
|
||||
this->last_position_ = a_cover->position;
|
||||
if (a_cover->position == COVER_OPEN)
|
||||
this->trigger();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected:
|
||||
float last_position_{NAN};
|
||||
};
|
||||
|
||||
class CoverClosedTrigger : public Trigger<> {
|
||||
public:
|
||||
CoverClosedTrigger(Cover *a_cover) {
|
||||
a_cover->add_on_state_callback([this, a_cover]() {
|
||||
if (a_cover->is_fully_closed()) {
|
||||
this->trigger();
|
||||
if (a_cover->position != this->last_position_) {
|
||||
this->last_position_ = a_cover->position;
|
||||
if (a_cover->position == COVER_CLOSED)
|
||||
this->trigger();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected:
|
||||
float last_position_{NAN};
|
||||
};
|
||||
|
||||
template<CoverOperation OP> class CoverTrigger : public Trigger<> {
|
||||
public:
|
||||
CoverTrigger(Cover *a_cover) {
|
||||
a_cover->add_on_state_callback([this, a_cover]() {
|
||||
auto current_op = a_cover->current_operation;
|
||||
if (current_op == OP) {
|
||||
if (!this->last_operation_.has_value() || this->last_operation_.value() != OP) {
|
||||
this->trigger();
|
||||
}
|
||||
}
|
||||
this->last_operation_ = current_op;
|
||||
});
|
||||
}
|
||||
|
||||
protected:
|
||||
optional<CoverOperation> last_operation_{};
|
||||
};
|
||||
} // namespace esphome::cover
|
||||
|
||||
@@ -10,9 +10,6 @@ namespace esphome::cover {
|
||||
|
||||
static const char *const TAG = "cover";
|
||||
|
||||
const float COVER_OPEN = 1.0f;
|
||||
const float COVER_CLOSED = 0.0f;
|
||||
|
||||
const LogString *cover_command_to_str(float pos) {
|
||||
if (pos == COVER_OPEN) {
|
||||
return LOG_STR("OPEN");
|
||||
@@ -153,23 +150,23 @@ void Cover::publish_state(bool save) {
|
||||
this->position = clamp(this->position, 0.0f, 1.0f);
|
||||
this->tilt = clamp(this->tilt, 0.0f, 1.0f);
|
||||
|
||||
ESP_LOGD(TAG, "'%s' >>", this->name_.c_str());
|
||||
ESP_LOGV(TAG, "'%s' >>", this->name_.c_str());
|
||||
auto traits = this->get_traits();
|
||||
if (traits.get_supports_position()) {
|
||||
ESP_LOGD(TAG, " Position: %.0f%%", this->position * 100.0f);
|
||||
ESP_LOGV(TAG, " Position: %.0f%%", this->position * 100.0f);
|
||||
} else {
|
||||
if (this->position == COVER_OPEN) {
|
||||
ESP_LOGD(TAG, " State: OPEN");
|
||||
ESP_LOGV(TAG, " State: OPEN");
|
||||
} else if (this->position == COVER_CLOSED) {
|
||||
ESP_LOGD(TAG, " State: CLOSED");
|
||||
ESP_LOGV(TAG, " State: CLOSED");
|
||||
} else {
|
||||
ESP_LOGD(TAG, " State: UNKNOWN");
|
||||
ESP_LOGV(TAG, " State: UNKNOWN");
|
||||
}
|
||||
}
|
||||
if (traits.get_supports_tilt()) {
|
||||
ESP_LOGD(TAG, " Tilt: %.0f%%", this->tilt * 100.0f);
|
||||
ESP_LOGV(TAG, " Tilt: %.0f%%", this->tilt * 100.0f);
|
||||
}
|
||||
ESP_LOGD(TAG, " Current Operation: %s", LOG_STR_ARG(cover_operation_to_str(this->current_operation)));
|
||||
ESP_LOGV(TAG, " Current Operation: %s", LOG_STR_ARG(cover_operation_to_str(this->current_operation)));
|
||||
|
||||
this->state_callback_.call();
|
||||
#if defined(USE_COVER) && defined(USE_CONTROLLER_REGISTRY)
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
namespace esphome::cover {
|
||||
|
||||
const extern float COVER_OPEN;
|
||||
const extern float COVER_CLOSED;
|
||||
static constexpr const float COVER_OPEN = 1.0f;
|
||||
static constexpr const float COVER_CLOSED = 0.0f;
|
||||
|
||||
#define LOG_COVER(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
// Once the API is considered stable, this warning will be removed.
|
||||
|
||||
#include "esphome/components/infrared/infrared.h"
|
||||
#include "esphome/components/remote_transmitter/remote_transmitter.h"
|
||||
#include "esphome/components/remote_receiver/remote_receiver.h"
|
||||
|
||||
namespace esphome::ir_rf_proxy {
|
||||
|
||||
|
||||
18
tests/components/ir_rf_proxy/common-rx.yaml
Normal file
18
tests/components/ir_rf_proxy/common-rx.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
remote_receiver:
|
||||
id: ir_receiver
|
||||
pin: ${rx_pin}
|
||||
|
||||
# Test various hardware types with transmitter/receiver using infrared platform
|
||||
infrared:
|
||||
# Infrared receiver
|
||||
- platform: ir_rf_proxy
|
||||
id: ir_rx
|
||||
name: "IR Receiver"
|
||||
remote_receiver_id: ir_receiver
|
||||
|
||||
# RF 900MHz receiver
|
||||
- platform: ir_rf_proxy
|
||||
id: rf_900_rx
|
||||
name: "RF 900 Receiver"
|
||||
frequency: 900 MHz
|
||||
remote_receiver_id: ir_receiver
|
||||
19
tests/components/ir_rf_proxy/common-tx.yaml
Normal file
19
tests/components/ir_rf_proxy/common-tx.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
remote_transmitter:
|
||||
id: ir_transmitter
|
||||
pin: ${tx_pin}
|
||||
carrier_duty_percent: 50%
|
||||
|
||||
# Test various hardware types with transmitter/receiver using infrared platform
|
||||
infrared:
|
||||
# Infrared transmitter
|
||||
- platform: ir_rf_proxy
|
||||
id: ir_tx
|
||||
name: "IR Transmitter"
|
||||
remote_transmitter_id: ir_transmitter
|
||||
|
||||
# RF 433MHz transmitter
|
||||
- platform: ir_rf_proxy
|
||||
id: rf_433_tx
|
||||
name: "RF 433 Transmitter"
|
||||
frequency: 433 MHz
|
||||
remote_transmitter_id: ir_transmitter
|
||||
@@ -1,42 +1,7 @@
|
||||
network:
|
||||
|
||||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
api:
|
||||
|
||||
remote_transmitter:
|
||||
id: ir_transmitter
|
||||
pin: ${tx_pin}
|
||||
carrier_duty_percent: 50%
|
||||
|
||||
remote_receiver:
|
||||
id: ir_receiver
|
||||
pin: ${rx_pin}
|
||||
|
||||
# Test various hardware types with transmitter/receiver using infrared platform
|
||||
infrared:
|
||||
# Infrared transmitter
|
||||
- platform: ir_rf_proxy
|
||||
id: ir_tx
|
||||
name: "IR Transmitter"
|
||||
remote_transmitter_id: ir_transmitter
|
||||
|
||||
# Infrared receiver
|
||||
- platform: ir_rf_proxy
|
||||
id: ir_rx
|
||||
name: "IR Receiver"
|
||||
remote_receiver_id: ir_receiver
|
||||
|
||||
# RF 433MHz transmitter
|
||||
- platform: ir_rf_proxy
|
||||
id: rf_433_tx
|
||||
name: "RF 433 Transmitter"
|
||||
frequency: 433 MHz
|
||||
remote_transmitter_id: ir_transmitter
|
||||
|
||||
# RF 900MHz receiver
|
||||
- platform: ir_rf_proxy
|
||||
id: rf_900_rx
|
||||
name: "RF 900 Receiver"
|
||||
frequency: 900 MHz
|
||||
remote_receiver_id: ir_receiver
|
||||
|
||||
7
tests/components/ir_rf_proxy/test-rx.esp32-idf.yaml
Normal file
7
tests/components/ir_rf_proxy/test-rx.esp32-idf.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
rx: !include common-rx.yaml
|
||||
7
tests/components/ir_rf_proxy/test-rx.esp8266-ard.yaml
Normal file
7
tests/components/ir_rf_proxy/test-rx.esp8266-ard.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
rx: !include common-rx.yaml
|
||||
7
tests/components/ir_rf_proxy/test-rx.rp2040-ard.yaml
Normal file
7
tests/components/ir_rf_proxy/test-rx.rp2040-ard.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
rx: !include common-rx.yaml
|
||||
7
tests/components/ir_rf_proxy/test-tx.esp32-idf.yaml
Normal file
7
tests/components/ir_rf_proxy/test-tx.esp32-idf.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
tx: !include common-tx.yaml
|
||||
7
tests/components/ir_rf_proxy/test-tx.esp8266-ard.yaml
Normal file
7
tests/components/ir_rf_proxy/test-tx.esp8266-ard.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
tx: !include common-tx.yaml
|
||||
7
tests/components/ir_rf_proxy/test-tx.rp2040-ard.yaml
Normal file
7
tests/components/ir_rf_proxy/test-tx.rp2040-ard.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
tx: !include common-tx.yaml
|
||||
8
tests/components/ir_rf_proxy/test.bk72xx-ard.yaml
Normal file
8
tests/components/ir_rf_proxy/test.bk72xx-ard.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
rx: !include common-rx.yaml
|
||||
tx: !include common-tx.yaml
|
||||
@@ -2,4 +2,7 @@ substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
<<: !include common.yaml
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
rx: !include common-rx.yaml
|
||||
tx: !include common-tx.yaml
|
||||
|
||||
@@ -2,4 +2,7 @@ substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
<<: !include common.yaml
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
rx: !include common-rx.yaml
|
||||
tx: !include common-tx.yaml
|
||||
|
||||
@@ -2,4 +2,7 @@ substitutions:
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
|
||||
<<: !include common.yaml
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
rx: !include common-rx.yaml
|
||||
tx: !include common-tx.yaml
|
||||
|
||||
@@ -245,6 +245,44 @@ cover:
|
||||
stop_action:
|
||||
- logger.log: stop_action
|
||||
optimistic: true
|
||||
- platform: template
|
||||
name: "Template Cover with Triggers"
|
||||
id: template_cover_with_triggers
|
||||
lambda: |-
|
||||
if (id(some_binary_sensor).state) {
|
||||
return COVER_OPEN;
|
||||
}
|
||||
return COVER_CLOSED;
|
||||
open_action:
|
||||
- logger.log: open_action
|
||||
close_action:
|
||||
- logger.log: close_action
|
||||
stop_action:
|
||||
- logger.log: stop_action
|
||||
optimistic: true
|
||||
on_open:
|
||||
- logger.log: "Cover on_open (deprecated)"
|
||||
on_opened:
|
||||
- logger.log: "Cover fully opened"
|
||||
on_closed:
|
||||
- logger.log: "Cover fully closed"
|
||||
on_opening:
|
||||
- logger.log: "Cover started opening"
|
||||
on_closing:
|
||||
- logger.log: "Cover started closing"
|
||||
on_idle:
|
||||
- logger.log: "Cover stopped moving"
|
||||
- logger.log: "Cover stopped moving"
|
||||
- if:
|
||||
condition:
|
||||
cover.is_open: template_cover_with_triggers
|
||||
then:
|
||||
logger.log: Cover is open
|
||||
- if:
|
||||
condition:
|
||||
cover.is_closed: template_cover_with_triggers
|
||||
then:
|
||||
logger.log: Cover is closed
|
||||
|
||||
number:
|
||||
- platform: template
|
||||
|
||||
Reference in New Issue
Block a user