mirror of
https://github.com/esphome/esphome.git
synced 2024-11-24 16:08:10 +01:00
Add command filters to the triggers
This commit is contained in:
parent
c83b68460c
commit
7931a307b4
3 changed files with 55 additions and 18 deletions
|
@ -1,7 +1,7 @@
|
||||||
from esphome import automation
|
from esphome import automation
|
||||||
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_DATA, CONF_ID, CONF_TRIGGER_ID
|
from esphome.const import CONF_COMMAND, CONF_DATA, CONF_ID, CONF_TRIGGER_ID
|
||||||
from esphome.core import CORE
|
from esphome.core import CORE
|
||||||
|
|
||||||
CODEOWNERS = ["@nielsnl68", "@jesserockz"]
|
CODEOWNERS = ["@nielsnl68", "@jesserockz"]
|
||||||
|
@ -66,16 +66,19 @@ CONFIG_SCHEMA = cv.Schema(
|
||||||
cv.Optional(CONF_ON_RECEIVE): automation.validate_automation(
|
cv.Optional(CONF_ON_RECEIVE): automation.validate_automation(
|
||||||
{
|
{
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESPNowReceiveTrigger),
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESPNowReceiveTrigger),
|
||||||
|
cv.Optional(CONF_COMMAND): cv.Range(min=16, max=255),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_ON_SENT): automation.validate_automation(
|
cv.Optional(CONF_ON_SENT): automation.validate_automation(
|
||||||
{
|
{
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESPNowSentTrigger),
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESPNowSentTrigger),
|
||||||
|
cv.Optional(CONF_COMMAND): cv.Range(min=16, max=255),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_ON_NEW_PEER): automation.validate_automation(
|
cv.Optional(CONF_ON_NEW_PEER): automation.validate_automation(
|
||||||
{
|
{
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESPNowNewPeerTrigger),
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESPNowNewPeerTrigger),
|
||||||
|
cv.Optional(CONF_COMMAND): cv.Range(min=16, max=255),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_PEERS): cv.ensure_list(cv.mac_address),
|
cv.Optional(CONF_PEERS): cv.ensure_list(cv.mac_address),
|
||||||
|
@ -101,6 +104,8 @@ async def to_code(config):
|
||||||
|
|
||||||
for conf in config.get(CONF_ON_SENT, []):
|
for conf in config.get(CONF_ON_SENT, []):
|
||||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
if CONF_COMMAND in conf:
|
||||||
|
cg.add(trigger.set_command(conf[CONF_COMMAND]))
|
||||||
await automation.build_automation(
|
await automation.build_automation(
|
||||||
trigger,
|
trigger,
|
||||||
[(ESPNowPacketConst, "packet"), (bool, "status")],
|
[(ESPNowPacketConst, "packet"), (bool, "status")],
|
||||||
|
@ -109,12 +114,16 @@ async def to_code(config):
|
||||||
|
|
||||||
for conf in config.get(CONF_ON_RECEIVE, []):
|
for conf in config.get(CONF_ON_RECEIVE, []):
|
||||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
if CONF_COMMAND in conf:
|
||||||
|
cg.add(trigger.set_command(conf[CONF_COMMAND]))
|
||||||
await automation.build_automation(
|
await automation.build_automation(
|
||||||
trigger, [(ESPNowPacketConst, "packet")], conf
|
trigger, [(ESPNowPacketConst, "packet")], conf
|
||||||
)
|
)
|
||||||
|
|
||||||
for conf in config.get(CONF_ON_NEW_PEER, []):
|
for conf in config.get(CONF_ON_NEW_PEER, []):
|
||||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
if CONF_COMMAND in conf:
|
||||||
|
cg.add(trigger.set_command(conf[CONF_COMMAND]))
|
||||||
await automation.build_automation(
|
await automation.build_automation(
|
||||||
trigger, [(ESPNowPacketConst, "packet")], conf
|
trigger, [(ESPNowPacketConst, "packet")], conf
|
||||||
)
|
)
|
||||||
|
@ -144,6 +153,7 @@ async def register_protocol(var, config):
|
||||||
cv.GenerateID(): cv.use_id(ESPNowComponent),
|
cv.GenerateID(): cv.use_id(ESPNowComponent),
|
||||||
cv.Optional(CONF_PEER): cv.templatable(cv.mac_address),
|
cv.Optional(CONF_PEER): cv.templatable(cv.mac_address),
|
||||||
cv.Required(CONF_DATA): cv.templatable(validate_raw_data),
|
cv.Required(CONF_DATA): cv.templatable(validate_raw_data),
|
||||||
|
cv.Optional(CONF_COMMAND): cv.templatable(cv.Range(min=16, max=255)),
|
||||||
},
|
},
|
||||||
key=CONF_DATA,
|
key=CONF_DATA,
|
||||||
),
|
),
|
||||||
|
@ -155,6 +165,10 @@ async def send_action(config, action_id, template_arg, args):
|
||||||
template_ = await cg.templatable(config[CONF_PEER].as_hex, args, cg.uint64)
|
template_ = await cg.templatable(config[CONF_PEER].as_hex, args, cg.uint64)
|
||||||
cg.add(var.set_mac(template_))
|
cg.add(var.set_mac(template_))
|
||||||
|
|
||||||
|
if CONF_COMMAND in config:
|
||||||
|
template_ = await cg.templatable(config[CONF_COMMAND], args, cg.uint8)
|
||||||
|
cg.add(var.set_command(template_))
|
||||||
|
|
||||||
data = config.get(CONF_DATA, [])
|
data = config.get(CONF_DATA, [])
|
||||||
if isinstance(data, bytes):
|
if isinstance(data, bytes):
|
||||||
data = list(data)
|
data = list(data)
|
||||||
|
@ -178,13 +192,6 @@ async def send_action(config, action_id, template_arg, args):
|
||||||
key=CONF_PEER,
|
key=CONF_PEER,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
async def new_peer_action(config, action_id, template_arg, args):
|
|
||||||
var = cg.new_Pvariable(action_id, template_arg)
|
|
||||||
template_ = await cg.templatable(config[CONF_PEER].as_hex, args, cg.uint64)
|
|
||||||
cg.add(var.set_mac(template_))
|
|
||||||
return var
|
|
||||||
|
|
||||||
|
|
||||||
@automation.register_action(
|
@automation.register_action(
|
||||||
"espnow.peer.del",
|
"espnow.peer.del",
|
||||||
DelPeerAction,
|
DelPeerAction,
|
||||||
|
|
|
@ -344,9 +344,10 @@ void ESPNowComponent::on_data_sent(const uint8_t *mac_addr, esp_now_send_status_
|
||||||
|
|
||||||
/* ESPNowProtocol ********************************************************************** */
|
/* ESPNowProtocol ********************************************************************** */
|
||||||
|
|
||||||
bool ESPNowProtocol::send(uint64_t peer, const uint8_t *data, uint8_t len) {
|
bool ESPNowProtocol::send(uint64_t peer, const uint8_t *data, uint8_t len, uint8_t command = 0) {
|
||||||
ESPNowPacket packet(peer, data, len, this->get_protocol_component_id()); // NOLINT
|
ESPNowPacket packet(peer, data, len, this->get_protocol_component_id()); // NOLINT
|
||||||
packet.set_sequents(this->get_next_sequents());
|
packet.set_sequents(this->get_next_sequents(packet.peer, packet.protocol()));
|
||||||
|
packet.set_command(command);
|
||||||
return this->parent_->send(packet);
|
return this->parent_->send(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ static const uint64_t ESPNOW_BROADCAST_ADDR = 0xFFFFFFFFFFFF;
|
||||||
|
|
||||||
static const uint8_t MAX_ESPNOW_DATA_SIZE = 241;
|
static const uint8_t MAX_ESPNOW_DATA_SIZE = 241;
|
||||||
|
|
||||||
static const uint8_t TRANSPORT_HEADER[] = {'N', '0', 'w'};
|
static const uint8_t TRANSPORT_HEADER[3] = {'N', '0', 'w'};
|
||||||
static const uint32_t ESPNOW_MAIN_PROTOCOL_ID = 0x447453; // = StD
|
static const uint32_t ESPNOW_MAIN_PROTOCOL_ID = 0x447453; // = StD
|
||||||
|
|
||||||
static const uint8_t ESPNOW_COMMAND_ACK = 0x06;
|
static const uint8_t ESPNOW_COMMAND_ACK = 0x06;
|
||||||
|
@ -129,7 +129,7 @@ class ESPNowProtocol : public Parented<ESPNowComponent> {
|
||||||
virtual void on_new_peer(const ESPNowPacket &packet){};
|
virtual void on_new_peer(const ESPNowPacket &packet){};
|
||||||
|
|
||||||
virtual uint32_t get_protocol_component_id() = 0;
|
virtual uint32_t get_protocol_component_id() = 0;
|
||||||
uint8_t get_next_sequents() {
|
uint8_t get_next_sequents(uint64_t peer = 0, uint32_t protocol = 0) {
|
||||||
if (this->next_sequents_ == 255) {
|
if (this->next_sequents_ == 255) {
|
||||||
this->next_sequents_ = 0;
|
this->next_sequents_ = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -145,7 +145,7 @@ class ESPNowProtocol : public Parented<ESPNowComponent> {
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool send(uint64_t peer, const uint8_t *data, uint8_t len);
|
bool send(uint64_t peer, const uint8_t *data, uint8_t len, uint8_t command = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint8_t next_sequents_{255};
|
uint8_t next_sequents_{255};
|
||||||
|
@ -260,6 +260,8 @@ class ESPNowComponent : public Component {
|
||||||
template<typename... Ts> class SendAction : public Action<Ts...>, public Parented<ESPNowComponent> {
|
template<typename... Ts> class SendAction : public Action<Ts...>, public Parented<ESPNowComponent> {
|
||||||
public:
|
public:
|
||||||
template<typename V> void set_mac(V mac) { this->mac_ = mac; }
|
template<typename V> void set_mac(V mac) { this->mac_ = mac; }
|
||||||
|
template<typename V> void set_command(V command) { this->command_ = command; }
|
||||||
|
|
||||||
void set_data_template(std::function<ByteBuffer(Ts...)> func) {
|
void set_data_template(std::function<ByteBuffer(Ts...)> func) {
|
||||||
this->data_func_ = func;
|
this->data_func_ = func;
|
||||||
this->static_ = false;
|
this->static_ = false;
|
||||||
|
@ -271,6 +273,10 @@ template<typename... Ts> class SendAction : public Action<Ts...>, public Parente
|
||||||
|
|
||||||
void play(Ts... x) override {
|
void play(Ts... x) override {
|
||||||
uint64_t mac = this->mac_.value(x...);
|
uint64_t mac = this->mac_.value(x...);
|
||||||
|
uint8_t command = 0;
|
||||||
|
if (this->command_.has_value()) {
|
||||||
|
command = this->mac_.value(x...);
|
||||||
|
}
|
||||||
|
|
||||||
if (this->static_) {
|
if (this->static_) {
|
||||||
this->parent_->get_default_protocol()->send(mac, this->data_static_.data(), this->data_static_.size());
|
this->parent_->get_default_protocol()->send(mac, this->data_static_.data(), this->data_static_.size());
|
||||||
|
@ -281,6 +287,7 @@ template<typename... Ts> class SendAction : public Action<Ts...>, public Parente
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
TemplatableValue<uint8_t, Ts...> command_{};
|
||||||
TemplatableValue<uint64_t, Ts...> mac_{};
|
TemplatableValue<uint64_t, Ts...> mac_{};
|
||||||
bool static_{false};
|
bool static_{false};
|
||||||
std::function<ByteBuffer(Ts...)> data_func_{};
|
std::function<ByteBuffer(Ts...)> data_func_{};
|
||||||
|
@ -314,24 +321,46 @@ template<typename... Ts> class DelPeerAction : public Action<Ts...>, public Pare
|
||||||
class ESPNowSentTrigger : public Trigger<const ESPNowPacket, bool> {
|
class ESPNowSentTrigger : public Trigger<const ESPNowPacket, bool> {
|
||||||
public:
|
public:
|
||||||
explicit ESPNowSentTrigger(ESPNowComponent *parent) {
|
explicit ESPNowSentTrigger(ESPNowComponent *parent) {
|
||||||
parent->get_default_protocol()->add_on_sent_callback(
|
parent->get_default_protocol()->add_on_sent_callback([this](const ESPNowPacket packet, bool status) {
|
||||||
[this](const ESPNowPacket packet, bool status) { this->trigger(packet, status); });
|
if ((this->command_ == 0) || this->command_ == packet.get_command()) {
|
||||||
|
this->trigger(packet, status);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
void set_command(uint8_t command) { this->command_ = command; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint8_t command_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
class ESPNowReceiveTrigger : public Trigger<const ESPNowPacket> {
|
class ESPNowReceiveTrigger : public Trigger<const ESPNowPacket> {
|
||||||
public:
|
public:
|
||||||
explicit ESPNowReceiveTrigger(ESPNowComponent *parent) {
|
explicit ESPNowReceiveTrigger(ESPNowComponent *parent) {
|
||||||
parent->get_default_protocol()->add_on_receive_callback(
|
parent->get_default_protocol()->add_on_receive_callback([this](const ESPNowPacket packet) {
|
||||||
[this](const ESPNowPacket packet) { this->trigger(packet); });
|
if ((this->command_ == 0) || this->command_ == packet.get_command()) {
|
||||||
|
this->trigger(packet);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
void set_command(uint8_t command) { this->command_ = command; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint8_t command_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
class ESPNowNewPeerTrigger : public Trigger<const ESPNowPacket> {
|
class ESPNowNewPeerTrigger : public Trigger<const ESPNowPacket> {
|
||||||
public:
|
public:
|
||||||
explicit ESPNowNewPeerTrigger(ESPNowComponent *parent) {
|
explicit ESPNowNewPeerTrigger(ESPNowComponent *parent) {
|
||||||
parent->get_default_protocol()->add_on_peer_callback([this](const ESPNowPacket packet) { this->trigger(packet); });
|
parent->get_default_protocol()->add_on_peer_callback([this](const ESPNowPacket packet) {
|
||||||
|
if ((this->command_ == 0) || this->command_ == packet.get_command()) {
|
||||||
|
this->trigger(packet);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
void set_command(uint8_t command) { this->command_ = command; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint8_t command_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace espnow
|
} // namespace espnow
|
||||||
|
|
Loading…
Reference in a new issue