mirror of
https://github.com/esphome/esphome.git
synced 2024-11-27 17:27:59 +01:00
-add option to set a global keeper to be used withe the espnow.send action. peer= keeper
- the keeper is templatable. - introduce protocol modes Keeper, drudge and universal - revert back event call's - add get)iwb_peer_address() - prepare for pairing protocol
This commit is contained in:
parent
342a20a48e
commit
535c8dd70f
5 changed files with 356 additions and 126 deletions
|
@ -8,6 +8,8 @@ CODEOWNERS = ["@nielsnl68", "@jesserockz"]
|
||||||
|
|
||||||
espnow_ns = cg.esphome_ns.namespace("espnow")
|
espnow_ns = cg.esphome_ns.namespace("espnow")
|
||||||
ESPNowComponent = espnow_ns.class_("ESPNowComponent", cg.Component)
|
ESPNowComponent = espnow_ns.class_("ESPNowComponent", cg.Component)
|
||||||
|
ESPNowProtocol = espnow_ns.class_("ESPNowProtocol")
|
||||||
|
|
||||||
ESPNowListener = espnow_ns.class_("ESPNowListener")
|
ESPNowListener = espnow_ns.class_("ESPNowListener")
|
||||||
|
|
||||||
ESPNowPacket = espnow_ns.class_("ESPNowPacket")
|
ESPNowPacket = espnow_ns.class_("ESPNowPacket")
|
||||||
|
@ -46,10 +48,20 @@ CONF_PEER = "peer"
|
||||||
CONF_PEERS = "peers"
|
CONF_PEERS = "peers"
|
||||||
CONF_USE_SENT_CHECK = "use_sent_check"
|
CONF_USE_SENT_CHECK = "use_sent_check"
|
||||||
CONF_WIFI_CHANNEL = "wifi_channel"
|
CONF_WIFI_CHANNEL = "wifi_channel"
|
||||||
|
CONF_PROTOCOL_MODE = "protocol_mode"
|
||||||
|
CONF_KEEPER = "keeper"
|
||||||
|
|
||||||
CONF_MAC_CHARS = "0123456789-AbCdEfGhIjKlMnOpQrStUvWxYz+aBcDeFgHiJkLmNoPqRsTuVwXyZ"
|
CONF_MAC_CHARS = "0123456789-AbCdEfGhIjKlMnOpQrStUvWxYz+aBcDeFgHiJkLmNoPqRsTuVwXyZ"
|
||||||
|
|
||||||
|
validate_command = cv.Range(min=1, max=250)
|
||||||
|
|
||||||
|
ESPNowProtocol_mode = espnow_ns.enum("ESPNowProtocol_mode")
|
||||||
|
ENUM_MODE = {
|
||||||
|
"universal": ESPNowProtocol_mode.universal,
|
||||||
|
"keeper": ESPNowProtocol_mode.keeper,
|
||||||
|
"drudge": ESPNowProtocol_mode.drudge,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def validate_raw_data(value):
|
def validate_raw_data(value):
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
|
@ -83,15 +95,18 @@ def validate_peer(value):
|
||||||
if isinstance(value, (int)):
|
if isinstance(value, (int)):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
value = cv.string_strict(value)
|
||||||
|
|
||||||
|
if value.lower() == CONF_KEEPER:
|
||||||
|
return 0x0
|
||||||
|
|
||||||
if value.find(":") != -1:
|
if value.find(":") != -1:
|
||||||
return convert_mac_address(value)
|
return convert_mac_address(value)
|
||||||
|
|
||||||
if len(value) == 8:
|
if len(value) == 8:
|
||||||
value = cv.string_strict(value)
|
|
||||||
|
|
||||||
mac = 0
|
mac = 0
|
||||||
for x in value:
|
for x in range(8, 0, -1):
|
||||||
n = CONF_MAC_CHARS.find(x)
|
n = CONF_MAC_CHARS.find(value[x - 1])
|
||||||
if n == -1:
|
if n == -1:
|
||||||
raise cv.Invalid(f"peer code is invalid. ({value}|{x})")
|
raise cv.Invalid(f"peer code is invalid. ({value}|{x})")
|
||||||
mac = (mac << 6) + n
|
mac = (mac << 6) + n
|
||||||
|
@ -112,28 +127,29 @@ CONFIG_SCHEMA = cv.Schema(
|
||||||
CONF_CONFORMATION_TIMEOUT, default="5000ms"
|
CONF_CONFORMATION_TIMEOUT, default="5000ms"
|
||||||
): cv.positive_time_period_milliseconds,
|
): cv.positive_time_period_milliseconds,
|
||||||
cv.Optional(CONF_RETRIES, default=5): cv.int_range(min=1, max=10),
|
cv.Optional(CONF_RETRIES, default=5): cv.int_range(min=1, max=10),
|
||||||
|
cv.Optional(CONF_KEEPER): cv.templatable(validate_peer),
|
||||||
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_COMMAND): validate_command,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_ON_BROADCAST): automation.validate_automation(
|
cv.Optional(CONF_ON_BROADCAST): automation.validate_automation(
|
||||||
{
|
{
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESPNowBroadcaseTrigger),
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESPNowBroadcaseTrigger),
|
||||||
cv.Optional(CONF_COMMAND): cv.Range(min=0, max=255),
|
cv.Optional(CONF_COMMAND): validate_command,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
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=0, max=255),
|
cv.Optional(CONF_COMMAND): validate_command,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
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_COMMAND): validate_command,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_PEERS): cv.ensure_list(validate_peer),
|
cv.Optional(CONF_PEERS): cv.ensure_list(validate_peer),
|
||||||
|
@ -157,6 +173,10 @@ async def to_code(config):
|
||||||
cg.add(var.set_conformation_timeout(config[CONF_CONFORMATION_TIMEOUT]))
|
cg.add(var.set_conformation_timeout(config[CONF_CONFORMATION_TIMEOUT]))
|
||||||
cg.add(var.set_retries(config[CONF_RETRIES]))
|
cg.add(var.set_retries(config[CONF_RETRIES]))
|
||||||
|
|
||||||
|
if CONF_KEEPER in config:
|
||||||
|
template_ = await cg.templatable(config[CONF_KEEPER], [], cg.uint64)
|
||||||
|
cg.add(var.set_keeper(template_))
|
||||||
|
|
||||||
for conf in config.get(CONF_PEERS, []):
|
for conf in config.get(CONF_PEERS, []):
|
||||||
cg.add(var.add_peer(conf))
|
cg.add(var.add_peer(conf))
|
||||||
|
|
||||||
|
@ -198,24 +218,27 @@ async def to_code(config):
|
||||||
PROTOCOL_SCHEMA = cv.Schema(
|
PROTOCOL_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.GenerateID(CONF_ESPNOW): cv.use_id(ESPNowComponent),
|
cv.GenerateID(CONF_ESPNOW): cv.use_id(ESPNowComponent),
|
||||||
|
cv.Optional(CONF_PROTOCOL_MODE): cv.enum(ENUM_MODE, string=True),
|
||||||
},
|
},
|
||||||
cv.only_on_esp32,
|
cv.only_on_esp32,
|
||||||
).extend(cv.COMPONENT_SCHEMA)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def register_protocol(var, config):
|
async def register_protocol(var, config):
|
||||||
now = await cg.get_variable(config[CONF_ESPNOW])
|
now = await cg.get_variable(config[CONF_ESPNOW])
|
||||||
cg.add(now.register_protocol(var))
|
cg.add(now.register_protocol(var))
|
||||||
|
if config[CONF_PROTOCOL_MODE]:
|
||||||
|
cg.add(var.set_protocol_mode(config[CONF_PROTOCOL_MODE]))
|
||||||
|
|
||||||
|
|
||||||
@automation.register_action(
|
@automation.register_action(
|
||||||
"espnow.broatcast",
|
"espnow.broadcast",
|
||||||
SendAction,
|
SendAction,
|
||||||
cv.maybe_simple_value(
|
cv.maybe_simple_value(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.use_id(ESPNowComponent),
|
cv.GenerateID(): cv.use_id(ESPNowComponent),
|
||||||
cv.Required(CONF_PAYLOAD): cv.templatable(validate_raw_data),
|
cv.Required(CONF_PAYLOAD): cv.templatable(validate_raw_data),
|
||||||
cv.Optional(CONF_COMMAND): cv.templatable(cv.Range(min=16, max=255)),
|
cv.Optional(CONF_COMMAND): cv.templatable(validate_command),
|
||||||
},
|
},
|
||||||
key=CONF_PAYLOAD,
|
key=CONF_PAYLOAD,
|
||||||
),
|
),
|
||||||
|
@ -228,9 +251,7 @@ async def register_protocol(var, config):
|
||||||
cv.GenerateID(): cv.use_id(ESPNowComponent),
|
cv.GenerateID(): cv.use_id(ESPNowComponent),
|
||||||
cv.Required(CONF_PEER): cv.templatable(validate_peer),
|
cv.Required(CONF_PEER): cv.templatable(validate_peer),
|
||||||
cv.Required(CONF_PAYLOAD): cv.templatable(validate_raw_data),
|
cv.Required(CONF_PAYLOAD): cv.templatable(validate_raw_data),
|
||||||
cv.Optional(CONF_COMMAND, default=0): cv.templatable(
|
cv.Optional(CONF_COMMAND): cv.templatable(validate_command),
|
||||||
cv.Range(min=0, max=255)
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
@ -30,11 +30,13 @@ static const size_t SEND_BUFFER_SIZE = 200;
|
||||||
ESPNowComponent *ESPNowComponent::static_{nullptr}; // NOLINT
|
ESPNowComponent *ESPNowComponent::static_{nullptr}; // NOLINT
|
||||||
|
|
||||||
std::string espnow_encode_peer(uint64_t peer) {
|
std::string espnow_encode_peer(uint64_t peer) {
|
||||||
std::string str1 = "";
|
|
||||||
if (peer == FAILED) {
|
if (peer == FAILED) {
|
||||||
return "[Not Set]";
|
return "[Not Set]";
|
||||||
} else if (peer == ESPNOW_BROADCAST_ADDR)
|
} else if (peer == ESPNOW_BROADCAST_ADDR)
|
||||||
return "[BroadCast]";
|
return "[BroadCast]";
|
||||||
|
|
||||||
|
std::string str1 = "";
|
||||||
|
str1.reserve(8);
|
||||||
do {
|
do {
|
||||||
str1.push_back(chars[peer & 63]); // Add on the left
|
str1.push_back(chars[peer & 63]); // Add on the left
|
||||||
peer = peer >> 6;
|
peer = peer >> 6;
|
||||||
|
@ -63,10 +65,10 @@ ESPNowComponent::ESPNowComponent() { ESPNowComponent::static_ = this; } // NOLI
|
||||||
void ESPNowComponent::dump_config() {
|
void ESPNowComponent::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, "esp_now:");
|
ESP_LOGCONFIG(TAG, "esp_now:");
|
||||||
|
|
||||||
ESP_LOGCONFIG(TAG, " Own Peer Address: %s.", espnow_encode_peer(this->own_peer_address_).c_str());
|
ESP_LOGCONFIG(TAG, " Own Peer code: %s.", espnow_encode_peer(this->own_peer_address_).c_str());
|
||||||
|
ESP_LOGCONFIG(TAG, " Keeper Peer code: %s.", espnow_encode_peer(this->get_keeper()).c_str());
|
||||||
ESP_LOGCONFIG(TAG, " Wifi channel: %d.", this->wifi_channel_);
|
ESP_LOGCONFIG(TAG, " Wifi channel: %d.", this->wifi_channel_);
|
||||||
ESP_LOGCONFIG(TAG, " Auto add new peers: %s.", this->auto_add_peer_ ? "Yes" : "No");
|
ESP_LOGCONFIG(TAG, " Auto add new peers: %s.", this->auto_add_peer_ ? "Yes" : "No");
|
||||||
|
|
||||||
ESP_LOGCONFIG(TAG, " Use sent status: %s.", this->use_sent_check_ ? "Yes" : "No");
|
ESP_LOGCONFIG(TAG, " Use sent status: %s.", this->use_sent_check_ ? "Yes" : "No");
|
||||||
ESP_LOGCONFIG(TAG, " Convermation timeout: %" PRIx32 "ms.", this->conformation_timeout_);
|
ESP_LOGCONFIG(TAG, " Convermation timeout: %" PRIx32 "ms.", this->conformation_timeout_);
|
||||||
ESP_LOGCONFIG(TAG, " Send retries: %d.", this->retries_);
|
ESP_LOGCONFIG(TAG, " Send retries: %d.", this->retries_);
|
||||||
|
@ -142,7 +144,10 @@ void ESPNowComponent::setup() {
|
||||||
esp_wifi_get_mac(WIFI_IF_STA, (uint8_t *) &this->own_peer_address_);
|
esp_wifi_get_mac(WIFI_IF_STA, (uint8_t *) &this->own_peer_address_);
|
||||||
|
|
||||||
for (auto id : this->peers_) {
|
for (auto id : this->peers_) {
|
||||||
add_peer(id);
|
this->add_peer(id);
|
||||||
|
}
|
||||||
|
if (this->get_keeper() != 0) {
|
||||||
|
this->add_peer(this->get_keeper());
|
||||||
}
|
}
|
||||||
|
|
||||||
this->send_queue_ = xQueueCreate(SEND_BUFFER_SIZE, sizeof(ESPNowPacket));
|
this->send_queue_ = xQueueCreate(SEND_BUFFER_SIZE, sizeof(ESPNowPacket));
|
||||||
|
@ -172,16 +177,16 @@ void ESPNowComponent::espnow_task(void *param) {
|
||||||
ESPNowPacket packet; // NOLINT
|
ESPNowPacket packet; // NOLINT
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (xQueueReceive(this_espnow->receive_queue_, (void *) &packet, (TickType_t) 1) == pdTRUE) {
|
if (xQueueReceive(this_espnow->receive_queue_, (void *) &packet, (TickType_t) 1) == pdTRUE) {
|
||||||
uint8_t *mac = packet.get_peer();
|
if (packet.is_broadcast) {
|
||||||
if (!packet.is_broadcast || !this_espnow->call_on_broadcast_(packet)) {
|
this_espnow->call_on_broadcast_(packet);
|
||||||
if (!esp_now_is_peer_exist(mac) && !this_espnow->call_on_new_peer_(packet)) {
|
continue;
|
||||||
if (this_espnow->auto_add_peer_) {
|
} else if (!this_espnow->is_paired(packet.peer)) {
|
||||||
this_espnow->add_peer(packet.peer);
|
this_espnow->call_on_new_peer_(packet);
|
||||||
}
|
}
|
||||||
}
|
if (this_espnow->is_paired(packet.peer)) {
|
||||||
if (esp_now_is_peer_exist(mac)) {
|
|
||||||
this_espnow->call_on_receive_(packet);
|
this_espnow->call_on_receive_(packet);
|
||||||
}
|
} else {
|
||||||
|
ESP_LOGI(TAG, "message skipt, not paired.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (xQueueReceive(this_espnow->send_queue_, (void *) &packet, (TickType_t) 1) == pdTRUE) {
|
if (xQueueReceive(this_espnow->send_queue_, (void *) &packet, (TickType_t) 1) == pdTRUE) {
|
||||||
|
@ -218,26 +223,39 @@ void ESPNowComponent::espnow_task(void *param) {
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t ESPNowComponent::add_peer(uint64_t peer) {
|
esp_err_t ESPNowComponent::add_peer(uint64_t peer) {
|
||||||
|
esp_err_t result = ESP_OK;
|
||||||
if (!this->is_ready()) {
|
if (!this->is_ready()) {
|
||||||
this->peers_.push_back(peer);
|
this->peers_.push_back(peer);
|
||||||
return ESP_OK;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
this->del_peer(peer);
|
if (esp_now_is_peer_exist((uint8_t *) &peer)) {
|
||||||
|
result = esp_now_del_peer((uint8_t *) &peer);
|
||||||
|
if (result != ESP_OK)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
esp_now_peer_info_t peer_info = {};
|
esp_now_peer_info_t peer_info = {};
|
||||||
memset(&peer_info, 0, sizeof(esp_now_peer_info_t));
|
memset(&peer_info, 0, sizeof(esp_now_peer_info_t));
|
||||||
peer_info.channel = this->wifi_channel_;
|
peer_info.channel = this->wifi_channel_;
|
||||||
peer_info.encrypt = false;
|
peer_info.encrypt = false;
|
||||||
memcpy((void *) peer_info.peer_addr, (void *) &peer, 6);
|
memcpy((void *) peer_info.peer_addr, (void *) &peer, 6);
|
||||||
|
esp_err_t result = esp_now_add_peer(&peer_info);
|
||||||
return esp_now_add_peer(&peer_info);
|
if (result == ESP_OK) {
|
||||||
|
this->call_on_add_peer_(peer);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t ESPNowComponent::del_peer(uint64_t peer) {
|
esp_err_t ESPNowComponent::del_peer(uint64_t peer) {
|
||||||
if (esp_now_is_peer_exist((uint8_t *) &peer))
|
esp_err_t result = ESP_OK;
|
||||||
return esp_now_del_peer((uint8_t *) &peer);
|
if (esp_now_is_peer_exist((uint8_t *) &peer)) {
|
||||||
return ESP_OK;
|
esp_err_t result = esp_now_del_peer((uint8_t *) &peer);
|
||||||
|
if (result == ESP_OK) {
|
||||||
|
this->call_on_del_peer_(peer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESPNowDefaultProtocol *ESPNowComponent::get_default_protocol() {
|
ESPNowDefaultProtocol *ESPNowComponent::get_default_protocol() {
|
||||||
|
@ -255,36 +273,61 @@ ESPNowProtocol *ESPNowComponent::get_protocol_(uint32_t protocol) {
|
||||||
return this->protocols_[protocol];
|
return this->protocols_[protocol];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESPNowComponent::call_on_receive_(ESPNowPacket &packet) {
|
void ESPNowComponent::call_on_receive_(ESPNowPacket &packet) {
|
||||||
ESPNowProtocol *protocol = this->get_protocol_(packet.get_protocol());
|
ESPNowProtocol *protocol = this->get_protocol_(packet.get_protocol());
|
||||||
if (protocol != nullptr) {
|
if (protocol != nullptr) {
|
||||||
return protocol->on_receive(packet);
|
this->defer([protocol, packet]() { protocol->on_receive(packet); });
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESPNowComponent::call_on_broadcast_(ESPNowPacket &packet) {
|
void ESPNowComponent::call_on_broadcast_(ESPNowPacket &packet) {
|
||||||
ESPNowProtocol *protocol = this->get_protocol_(packet.get_protocol());
|
ESPNowProtocol *protocol = this->get_protocol_(packet.get_protocol());
|
||||||
if (protocol != nullptr) {
|
if (protocol != nullptr) {
|
||||||
return protocol->on_broadcast(packet);
|
this->defer([protocol, packet]() { protocol->on_broadcast(packet); });
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESPNowComponent::call_on_sent_(ESPNowPacket &packet, bool status) {
|
void ESPNowComponent::call_on_sent_(ESPNowPacket &packet, bool status) {
|
||||||
ESPNowProtocol *protocol = this->get_protocol_(packet.get_protocol());
|
ESPNowProtocol *protocol = this->get_protocol_(packet.get_protocol());
|
||||||
if (protocol != nullptr) {
|
if (protocol != nullptr) {
|
||||||
return protocol->on_sent(packet, status);
|
this->defer([protocol, packet, status]() { protocol->on_sent(packet, status); });
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESPNowComponent::call_on_new_peer_(ESPNowPacket &packet) {
|
void ESPNowComponent::call_on_new_peer_(ESPNowPacket &packet) {
|
||||||
ESPNowProtocol *protocol = this->get_protocol_(packet.get_protocol());
|
ESPNowProtocol *protocol = this->get_protocol_(packet.get_protocol());
|
||||||
if (protocol != nullptr) {
|
if (protocol != nullptr) {
|
||||||
return protocol->on_new_peer(packet);
|
this->defer([protocol, packet]() { protocol->on_new_peer(packet); });
|
||||||
}
|
}
|
||||||
return false;
|
}
|
||||||
|
|
||||||
|
void ESPNowComponent::call_on_add_peer_(uint64_t peer) {
|
||||||
|
this->defer([this, peer]() {
|
||||||
|
for (const auto &kv : this->protocols_) {
|
||||||
|
kv.second->on_add_peer(peer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESPNowComponent::call_on_del_peer_(uint64_t peer) {
|
||||||
|
this->defer([this, peer]() {
|
||||||
|
for (const auto &kv : this->protocols_) {
|
||||||
|
kv.second->on_del_peer(peer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESPNowComponent::is_paired(uint64_t peer) {
|
||||||
|
bool result = false;
|
||||||
|
if (this->pairing_protocol_ != nullptr) {
|
||||||
|
result = this->pairing_protocol_->is_paired(peer);
|
||||||
|
} else {
|
||||||
|
result = (esp_now_is_peer_exist((uint8_t *) &peer));
|
||||||
|
}
|
||||||
|
if (!result && this->auto_add_peer_) {
|
||||||
|
result = (this->add_peer(peer) == ESP_OK);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**< callback function of receiving ESPNOW data */
|
/**< callback function of receiving ESPNOW data */
|
||||||
|
@ -335,7 +378,7 @@ bool ESPNowComponent::send(ESPNowPacket packet) {
|
||||||
ESP_LOGE(TAG, "Cannot send espnow packet, espnow failed to setup");
|
ESP_LOGE(TAG, "Cannot send espnow packet, espnow failed to setup");
|
||||||
} else if (this->send_queue_full()) {
|
} else if (this->send_queue_full()) {
|
||||||
ESP_LOGE(TAG, "Send Buffer Out of Memory.");
|
ESP_LOGE(TAG, "Send Buffer Out of Memory.");
|
||||||
} else if (!esp_now_is_peer_exist(packet.get_peer())) {
|
} else if (!this->is_paired(packet.peer)) {
|
||||||
ESP_LOGE(TAG, "Peer not registered: %s.", packet.get_peer_code().c_str());
|
ESP_LOGE(TAG, "Peer not registered: %s.", packet.get_peer_code().c_str());
|
||||||
} else if (!packet.is_valid()) {
|
} else if (!packet.is_valid()) {
|
||||||
ESP_LOGE(TAG, "This Packet is invalid: %s (%d.%d)", packet.get_peer_code().c_str(), packet.get_sequents(),
|
ESP_LOGE(TAG, "This Packet is invalid: %s (%d.%d)", packet.get_peer_code().c_str(), packet.get_sequents(),
|
||||||
|
@ -382,6 +425,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, uint8_t command) {
|
bool ESPNowProtocol::send(uint64_t peer, const uint8_t *data, uint8_t len, uint8_t command) {
|
||||||
|
if (peer == 0x0) {
|
||||||
|
peer = this->get_keeper();
|
||||||
|
}
|
||||||
|
|
||||||
ESPNowPacket packet(peer, data, len, this->get_protocol_id(), command); // NOLINT
|
ESPNowPacket packet(peer, data, len, this->get_protocol_id(), command); // NOLINT
|
||||||
packet.set_sequents(this->get_next_sequents(packet.peer));
|
packet.set_sequents(this->get_next_sequents(packet.peer));
|
||||||
return this->parent_->send(packet);
|
return this->parent_->send(packet);
|
||||||
|
|
|
@ -15,13 +15,15 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <random>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace espnow {
|
namespace espnow {
|
||||||
|
|
||||||
static const uint64_t ESPNOW_BROADCAST_ADDR = 0xFFFFFFFFFFFF;
|
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 = 240;
|
||||||
|
|
||||||
static const uint8_t TRANSPORT_HEADER[3] = {'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
|
||||||
|
@ -33,6 +35,10 @@ static const uint8_t ESPNOW_COMMAND_RESEND = 0x05;
|
||||||
static const char chars[] = "0123456789-AbCdEfGhIjKlMnOpQrStUvWxYz+aBcDeFgHiJkLmNoPqRsTuVwXyZ";
|
static const char chars[] = "0123456789-AbCdEfGhIjKlMnOpQrStUvWxYz+aBcDeFgHiJkLmNoPqRsTuVwXyZ";
|
||||||
static const uint64_t FAILED = 0;
|
static const uint64_t FAILED = 0;
|
||||||
|
|
||||||
|
template<typename T> std::string espnow_i2h(T i) { return sprintf("%04x", i); }
|
||||||
|
|
||||||
|
std::string espnow_rdm(std::string::size_type length);
|
||||||
|
|
||||||
std::string espnow_encode_peer(uint64_t peer);
|
std::string espnow_encode_peer(uint64_t peer);
|
||||||
uint64_t espnow_decode_peer(std::string peer);
|
uint64_t espnow_decode_peer(std::string peer);
|
||||||
|
|
||||||
|
@ -96,9 +102,6 @@ struct ESPNowPacket {
|
||||||
uint8_t content_size() const { return (this->prefix_size() + this->size); }
|
uint8_t content_size() const { return (this->prefix_size() + this->size); }
|
||||||
|
|
||||||
inline void set_peer(const uint8_t *peer) ESPHOME_ALWAYS_INLINE {
|
inline void set_peer(const uint8_t *peer) ESPHOME_ALWAYS_INLINE {
|
||||||
if (*peer == 0) {
|
|
||||||
peer = (uint8_t *) &ESPNOW_BROADCAST_ADDR;
|
|
||||||
}
|
|
||||||
memcpy((void *) this->get_peer(), (const void *) peer, 6);
|
memcpy((void *) this->get_peer(), (const void *) peer, 6);
|
||||||
};
|
};
|
||||||
inline bool is_peer(const uint8_t *peer) const { return memcmp(peer, this->get_peer(), 6) == 0; }
|
inline bool is_peer(const uint8_t *peer) const { return memcmp(peer, this->get_peer(), 6) == 0; }
|
||||||
|
@ -137,33 +140,45 @@ struct ESPNowPacket {
|
||||||
|
|
||||||
class ESPNowComponent;
|
class ESPNowComponent;
|
||||||
|
|
||||||
|
enum ESPNowProtocol_mode { universal, keeper, drudge };
|
||||||
|
|
||||||
class ESPNowProtocol : public Parented<ESPNowComponent> {
|
class ESPNowProtocol : public Parented<ESPNowComponent> {
|
||||||
public:
|
public:
|
||||||
ESPNowProtocol(){};
|
void set_protocol_mode(ESPNowProtocol_mode mode) { this->protocol_mode_ = mode; }
|
||||||
|
ESPNowProtocol_mode get_protocol_mode() { return this->protocol_mode_; }
|
||||||
|
|
||||||
virtual bool on_receive(const ESPNowPacket &packet) { return false; };
|
protected:
|
||||||
virtual bool on_broadcast(const ESPNowPacket &packet) { return false; };
|
ESPNowProtocol_mode protocol_mode_{universal};
|
||||||
|
|
||||||
virtual bool on_sent(const ESPNowPacket &packet, bool status) { return false; };
|
|
||||||
virtual bool on_new_peer(const ESPNowPacket &packet) { return false; };
|
|
||||||
|
|
||||||
|
public:
|
||||||
virtual uint32_t get_protocol_id() = 0;
|
virtual uint32_t get_protocol_id() = 0;
|
||||||
virtual std::string get_protocol_name() = 0;
|
virtual std::string get_protocol_name() = 0;
|
||||||
|
virtual void init_protocol() {}
|
||||||
|
|
||||||
uint8_t get_next_sequents() { return this->get_next_sequents(0); }
|
virtual void on_receive(const ESPNowPacket &packet){};
|
||||||
virtual uint8_t get_next_sequents(uint64_t peer) {
|
virtual void on_broadcast(const ESPNowPacket &packet) { this->on_receive(packet); };
|
||||||
if (this->next_sequents_ == 255) {
|
|
||||||
this->next_sequents_ = 0;
|
virtual void on_sent(const ESPNowPacket &packet, bool status){};
|
||||||
|
virtual void on_new_peer(const ESPNowPacket &packet){};
|
||||||
|
|
||||||
|
virtual void on_add_peer(uint64_t peer){};
|
||||||
|
virtual void on_del_peer(uint64_t peer){};
|
||||||
|
|
||||||
|
virtual bool is_paired(uint64_t to_peer) { return true; }
|
||||||
|
|
||||||
|
uint8_t get_next_sequents(uint64_t peer) {
|
||||||
|
if (this->next_sequents_[peer] == 255) {
|
||||||
|
this->next_sequents_[peer] = 0;
|
||||||
} else {
|
} else {
|
||||||
this->next_sequents_++;
|
this->next_sequents_[peer]++;
|
||||||
}
|
}
|
||||||
return this->next_sequents_;
|
return this->next_sequents_[peer];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_valid_squence(uint8_t received_sequence) {
|
bool is_valid_squence(uint64_t peer, uint8_t received_sequence) {
|
||||||
bool valid = this->next_sequents_ + 1 == received_sequence;
|
bool valid = this->next_sequents_[peer] + 1 == received_sequence;
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this->next_sequents_ = received_sequence;
|
this->next_sequents_[peer] = received_sequence;
|
||||||
}
|
}
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
@ -171,7 +186,17 @@ class ESPNowProtocol : public Parented<ESPNowComponent> {
|
||||||
bool send(uint64_t peer, const uint8_t *data, uint8_t len, uint8_t command = 0);
|
bool send(uint64_t peer, const uint8_t *data, uint8_t len, uint8_t command = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint8_t next_sequents_{255};
|
std::map<uint64_t, uint8_t> next_sequents_{};
|
||||||
|
std::string get_mode_name_() {
|
||||||
|
switch (this->protocol_mode_) {
|
||||||
|
case universal:
|
||||||
|
return "Universal";
|
||||||
|
case keeper:
|
||||||
|
return "Keeper";
|
||||||
|
case drudge:
|
||||||
|
return "Drudge";
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ESPNowDefaultProtocol : public ESPNowProtocol {
|
class ESPNowDefaultProtocol : public ESPNowProtocol {
|
||||||
|
@ -182,35 +207,28 @@ class ESPNowDefaultProtocol : public ESPNowProtocol {
|
||||||
void add_on_receive_callback(std::function<void(const ESPNowPacket)> &&callback) {
|
void add_on_receive_callback(std::function<void(const ESPNowPacket)> &&callback) {
|
||||||
this->on_receive_.add(std::move(callback));
|
this->on_receive_.add(std::move(callback));
|
||||||
}
|
}
|
||||||
bool on_receive(const ESPNowPacket &packet) override {
|
void on_receive(const ESPNowPacket &packet) override { this->on_receive_.call(packet); };
|
||||||
this->on_receive_.call(packet);
|
|
||||||
return this->on_receive_.size() > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
void add_on_broadcast_callback(std::function<void(const ESPNowPacket)> &&callback) {
|
void add_on_broadcast_callback(std::function<void(const ESPNowPacket)> &&callback) {
|
||||||
this->on_broadcast_.add(std::move(callback));
|
this->on_broadcast_.add(std::move(callback));
|
||||||
}
|
}
|
||||||
|
void on_broadcast(const ESPNowPacket &packet) override {
|
||||||
bool on_broadcast(const ESPNowPacket &packet) override {
|
if (this->on_broadcast_.size() > 0) {
|
||||||
this->on_broadcast_.call(packet);
|
this->on_broadcast_.call(packet);
|
||||||
return this->on_broadcast_.size() > 0;
|
} else {
|
||||||
|
this->on_receive(packet);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void add_on_sent_callback(std::function<void(const ESPNowPacket, bool status)> &&callback) {
|
void add_on_sent_callback(std::function<void(const ESPNowPacket, bool status)> &&callback) {
|
||||||
this->on_sent_.add(std::move(callback));
|
this->on_sent_.add(std::move(callback));
|
||||||
}
|
}
|
||||||
bool on_sent(const ESPNowPacket &packet, bool status) override {
|
void on_sent(const ESPNowPacket &packet, bool status) override { this->on_sent_.call(packet, status); };
|
||||||
this->on_sent_.call(packet, status);
|
|
||||||
return this->on_sent_.size() > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
void add_on_peer_callback(std::function<void(const ESPNowPacket)> &&callback) {
|
void add_on_new_peer_callback(std::function<void(const ESPNowPacket)> &&callback) {
|
||||||
this->on_new_peer_.add(std::move(callback));
|
this->on_new_peer_.add(std::move(callback));
|
||||||
}
|
}
|
||||||
bool on_new_peer(const ESPNowPacket &packet) override {
|
void on_new_peer(const ESPNowPacket &packet) override { this->on_new_peer_.call(packet); };
|
||||||
this->on_new_peer_.call(packet);
|
|
||||||
return this->on_new_peer_.size() > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CallbackManager<void(const ESPNowPacket, bool)> on_sent_;
|
CallbackManager<void(const ESPNowPacket, bool)> on_sent_;
|
||||||
|
@ -240,62 +258,73 @@ class ESPNowComponent : public Component {
|
||||||
void set_use_sent_check(bool value) { this->use_sent_check_ = value; }
|
void set_use_sent_check(bool value) { this->use_sent_check_ = value; }
|
||||||
void set_conformation_timeout(uint32_t timeout) { this->conformation_timeout_ = timeout; }
|
void set_conformation_timeout(uint32_t timeout) { this->conformation_timeout_ = timeout; }
|
||||||
void set_retries(uint8_t value) { this->retries_ = value; }
|
void set_retries(uint8_t value) { this->retries_ = value; }
|
||||||
|
void set_pairing_protocol(ESPNowProtocol *pairing_protocol) { this->pairing_protocol_ = pairing_protocol; }
|
||||||
|
void set_keeper(uint64_t keeper) { this->keeper_ = keeper; }
|
||||||
|
} uint64_t get_keeper() {
|
||||||
|
return this->keeper_;
|
||||||
|
}
|
||||||
|
uint64_t get_own_peer_address() { return this->own_peer_address_; }
|
||||||
|
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void loop() override;
|
void loop() override;
|
||||||
|
|
||||||
bool send(ESPNowPacket packet);
|
bool is_paired(uint64_t to_peer);
|
||||||
|
|
||||||
void register_protocol(ESPNowProtocol *protocol) {
|
bool send(ESPNowPacket packet);
|
||||||
|
|
||||||
|
void register_protocol(ESPNowProtocol *protocol) {
|
||||||
protocol->set_parent(this);
|
protocol->set_parent(this);
|
||||||
this->protocols_[protocol->get_protocol_id()] = protocol;
|
this->protocols_[protocol->get_protocol_id()] = protocol;
|
||||||
}
|
protocol->init_protocol();
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t add_peer(uint64_t peer);
|
esp_err_t add_peer(uint64_t peer);
|
||||||
esp_err_t del_peer(uint64_t peer);
|
esp_err_t del_peer(uint64_t peer);
|
||||||
|
|
||||||
bool send_queue_empty() { return uxQueueMessagesWaiting(this->send_queue_) == 0; }
|
bool send_queue_empty() { return uxQueueMessagesWaiting(this->send_queue_) == 0; }
|
||||||
bool send_queue_full() { return uxQueueSpacesAvailable(this->send_queue_) == 0; }
|
bool send_queue_full() { return uxQueueSpacesAvailable(this->send_queue_) == 0; }
|
||||||
size_t send_queue_used() { return uxQueueMessagesWaiting(this->send_queue_); }
|
size_t send_queue_used() { return uxQueueMessagesWaiting(this->send_queue_); }
|
||||||
size_t send_queue_free() { return uxQueueSpacesAvailable(this->send_queue_); }
|
size_t send_queue_free() { return uxQueueSpacesAvailable(this->send_queue_); }
|
||||||
|
|
||||||
void lock() { this->lock_ = true; }
|
void lock() { this->lock_ = true; }
|
||||||
bool is_locked() { return this->lock_; }
|
bool is_locked() { return this->lock_; }
|
||||||
void unlock() { this->lock_ = false; }
|
void unlock() { this->lock_ = false; }
|
||||||
|
|
||||||
ESPNowDefaultProtocol *get_default_protocol();
|
ESPNowDefaultProtocol *get_default_protocol();
|
||||||
|
|
||||||
void show_packet(const std::string &title, const ESPNowPacket &packet);
|
void show_packet(const std::string &title, const ESPNowPacket &packet);
|
||||||
|
|
||||||
static void espnow_task(void *params);
|
static void espnow_task(void *params);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool validate_channel_(uint8_t channel);
|
bool validate_channel_(uint8_t channel);
|
||||||
ESPNowProtocol *get_protocol_(uint32_t protocol);
|
ESPNowProtocol *get_protocol_(uint32_t protocol);
|
||||||
|
ESPNowProtocol *pairing_protocol_{nullptr};
|
||||||
|
uint64_t own_peer_address_{0};
|
||||||
|
uint8_t wifi_channel_{0};
|
||||||
|
uint32_t conformation_timeout_{5000};
|
||||||
|
uint8_t retries_{5};
|
||||||
|
|
||||||
uint64_t own_peer_address_{0};
|
bool auto_add_peer_{false};
|
||||||
uint8_t wifi_channel_{0};
|
bool use_sent_check_{true};
|
||||||
|
|
||||||
uint32_t conformation_timeout_{5000};
|
bool lock_{false};
|
||||||
uint8_t retries_{5};
|
|
||||||
|
|
||||||
bool auto_add_peer_{false};
|
void call_on_receive_(ESPNowPacket &packet);
|
||||||
bool use_sent_check_{true};
|
void call_on_broadcast_(ESPNowPacket &packet);
|
||||||
|
void call_on_sent_(ESPNowPacket &packet, bool status);
|
||||||
|
void call_on_new_peer_(ESPNowPacket &packet);
|
||||||
|
|
||||||
bool lock_{false};
|
void call_on_add_peer_(uint64_t peer);
|
||||||
|
void call_on_del_peer_(uint64_t peer);
|
||||||
|
|
||||||
bool call_on_receive_(ESPNowPacket &packet);
|
QueueHandle_t receive_queue_{};
|
||||||
bool call_on_broadcast_(ESPNowPacket &packet);
|
QueueHandle_t send_queue_{};
|
||||||
bool call_on_sent_(ESPNowPacket &packet, bool status);
|
|
||||||
bool call_on_new_peer_(ESPNowPacket &packet);
|
|
||||||
|
|
||||||
QueueHandle_t receive_queue_{};
|
std::map<uint32_t, ESPNowProtocol *> protocols_{};
|
||||||
QueueHandle_t send_queue_{};
|
std::vector<uint64_t> peers_{};
|
||||||
|
bool task_running_{false};
|
||||||
std::map<uint32_t, ESPNowProtocol *> protocols_{};
|
static ESPNowComponent *static_; // NOLINT
|
||||||
std::vector<uint64_t> peers_{};
|
|
||||||
bool task_running_{false};
|
|
||||||
static ESPNowComponent *static_; // NOLINT
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Ts> class SendAction : public Action<Ts...>, public Parented<ESPNowComponent> {
|
template<typename... Ts> class SendAction : public Action<Ts...>, public Parented<ESPNowComponent> {
|
||||||
|
@ -380,7 +409,7 @@ class ESPNowBroadcaseTrigger : public Trigger<const ESPNowPacket> {
|
||||||
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) {
|
parent->get_default_protocol()->add_on_new_peer_callback([this](const ESPNowPacket packet) {
|
||||||
if ((this->command_ == 0) || this->command_ == packet.get_command()) {
|
if ((this->command_ == 0) || this->command_ == packet.get_command()) {
|
||||||
this->trigger(packet);
|
this->trigger(packet);
|
||||||
}
|
}
|
||||||
|
|
57
esphome/components/espnow/test1.yaml
Normal file
57
esphome/components/espnow/test1.yaml
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
# These substitutions allow the end user to override certain values
|
||||||
|
substitutions:
|
||||||
|
name: "lum-iot-test1"
|
||||||
|
friendly_name: "Project Template"
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
board: esp32dev
|
||||||
|
framework:
|
||||||
|
type: esp-idf
|
||||||
|
# version: 5.1.5
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: "${name}"
|
||||||
|
# Friendly names are used where appropriate in Home Assistant
|
||||||
|
friendly_name: "${friendly_name}"
|
||||||
|
# Automatically add the mac address to the name
|
||||||
|
# so you can use a single firmware for all devices
|
||||||
|
name_add_mac_suffix: false
|
||||||
|
|
||||||
|
# This will allow for (future) project identification,
|
||||||
|
# configuration and updates.
|
||||||
|
project:
|
||||||
|
name: LumenSoft.espnow-test
|
||||||
|
version: "1.0"
|
||||||
|
|
||||||
|
# To be able to get logs from the device via serial and api.
|
||||||
|
logger:
|
||||||
|
level: verbose
|
||||||
|
|
||||||
|
espnow:
|
||||||
|
auto_add_peer: false
|
||||||
|
peers:
|
||||||
|
- FF:FF:FF:FF:FF:FF
|
||||||
|
- flW1QA3k
|
||||||
|
|
||||||
|
on_receive:
|
||||||
|
- logger.log:
|
||||||
|
format: "Received: '%s' from '%s' command: %d RSSI: %d"
|
||||||
|
args:
|
||||||
|
[
|
||||||
|
packet.get_payload(),
|
||||||
|
packet.get_peer_code().c_str(),
|
||||||
|
packet.get_command(),
|
||||||
|
packet.rssi,
|
||||||
|
]
|
||||||
|
|
||||||
|
on_broadcast:
|
||||||
|
- command: 123
|
||||||
|
then:
|
||||||
|
- logger.log:
|
||||||
|
format: "Broadcast Received from: '%s' RSSI: %d: %s"
|
||||||
|
args:
|
||||||
|
[
|
||||||
|
packet.get_peer_code().c_str(),
|
||||||
|
packet.rssi,
|
||||||
|
packet.get_payload(),
|
||||||
|
]
|
76
esphome/components/espnow/test2.yaml
Normal file
76
esphome/components/espnow/test2.yaml
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
# These substitutions allow the end user to override certain values
|
||||||
|
substitutions:
|
||||||
|
name: "lum-iot-test2"
|
||||||
|
friendly_name: "Project Template"
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
board: esp32dev
|
||||||
|
framework:
|
||||||
|
type: esp-idf
|
||||||
|
# version: 5.1.5
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: "${name}"
|
||||||
|
# Friendly names are used where appropriate in Home Assistant
|
||||||
|
friendly_name: "${friendly_name}"
|
||||||
|
# Automatically add the mac address to the name
|
||||||
|
# so you can use a single firmware for all devices
|
||||||
|
name_add_mac_suffix: false
|
||||||
|
|
||||||
|
# This will allow for (future) project identification,
|
||||||
|
# configuration and updates.
|
||||||
|
project:
|
||||||
|
name: LumenSoft.espnow-test
|
||||||
|
version: "1.0"
|
||||||
|
|
||||||
|
# To be able to get logs from the device via serial and api.
|
||||||
|
logger:
|
||||||
|
level: verbose
|
||||||
|
|
||||||
|
espnow:
|
||||||
|
auto_add_peer: true
|
||||||
|
peers:
|
||||||
|
- FF:FF:FF:FF:FF:FF
|
||||||
|
keeper: rmT7YF9o
|
||||||
|
on_receive:
|
||||||
|
- logger.log:
|
||||||
|
format: "Received: '%s' from '%s' command: %d RSSI: %d"
|
||||||
|
args:
|
||||||
|
[
|
||||||
|
packet.get_payload(),
|
||||||
|
packet.get_peer_code().c_str(),
|
||||||
|
packet.get_command(),
|
||||||
|
packet.rssi,
|
||||||
|
]
|
||||||
|
|
||||||
|
on_broadcast:
|
||||||
|
- command: 123
|
||||||
|
then:
|
||||||
|
- logger.log:
|
||||||
|
format: "Broadcast Received from: '%s' RSSI: %d: %s"
|
||||||
|
args:
|
||||||
|
[
|
||||||
|
packet.get_peer_code().c_str(),
|
||||||
|
packet.rssi,
|
||||||
|
packet.get_payload(),
|
||||||
|
]
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 30sec
|
||||||
|
startup_delay: 20sec
|
||||||
|
then:
|
||||||
|
- espnow.broadcast:
|
||||||
|
payload: "Broadcast message"
|
||||||
|
command: 123
|
||||||
|
- interval: 5sec
|
||||||
|
then:
|
||||||
|
- espnow.send:
|
||||||
|
peer: keeper
|
||||||
|
payload: "tesing the test"
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: gpio
|
||||||
|
pin: GPIO39
|
||||||
|
name: Button
|
||||||
|
on_click:
|
||||||
|
- espnow.peer.del: rmT7YF9o
|
Loading…
Reference in a new issue