1
0
mirror of https://github.com/esphome/esphome.git synced 2025-02-01 02:31:00 +00:00

implement set channel possiblity

remove peer_id over the use of globals.
This commit is contained in:
NP v/d Spek 2024-11-26 22:31:52 +01:00
parent 7534e39cc4
commit 3250125e21
6 changed files with 91 additions and 133 deletions

View File

@ -1,5 +1,6 @@
from esphome import automation, core
import esphome.codegen as cg
from esphome.components.globals import GlobalsComponent
import esphome.config_validation as cv
from esphome.const import (
CONF_COMMAND,
@ -7,7 +8,9 @@ from esphome.const import (
CONF_MAC_ADDRESS,
CONF_PAYLOAD,
CONF_TRIGGER_ID,
CONF_WIFI,
)
import esphome.final_validate as fv
CODEOWNERS = ["@nielsnl68", "@jesserockz"]
@ -18,7 +21,7 @@ ESPNowProtocol = espnow_ns.class_("ESPNowProtocol")
ESPNowListener = espnow_ns.class_("ESPNowListener")
ESPNowPacket = espnow_ns.class_("ESPNowPacket")
ESPNowPeer = cg.uint64
ESPNowPeer = GlobalsComponent
ESPNowPacketConst = ESPNowPacket.operator("const")
@ -41,7 +44,7 @@ SendAction = espnow_ns.class_("SendAction", automation.Action)
NewPeerAction = espnow_ns.class_("NewPeerAction", automation.Action)
DelPeerAction = espnow_ns.class_("DelPeerAction", automation.Action)
SetKeeperAction = espnow_ns.class_("SetKeeperAction", automation.Action)
SetStaticPeerAction = espnow_ns.class_("SetStaticPeerAction", automation.Action)
SetChannelAction = espnow_ns.class_("SetChannelAction", automation.Action)
CONF_AUTO_ADD_PEER = "auto_add_peer"
CONF_CONFORMATION_TIMEOUT = "conformation_timeout"
@ -59,6 +62,7 @@ CONF_WIFI_CHANNEL = "wifi_channel"
CONF_PROTOCOL_MODE = "protocol_mode"
validate_command = cv.Range(min=1, max=250)
validate_channel = cv.int_range(1, 14)
ESPNowProtocolMode = espnow_ns.enum("ESPNowProtocolMode")
ENUM_MODE = {
@ -86,9 +90,8 @@ def espnow_hex(mac_address):
DEFINE_PEER_CONFIG = cv.maybe_simple_value(
{
cv.Optional(CONF_PEER_ID): cv.declare_id(ESPNowPeer),
cv.Required(CONF_MAC_ADDRESS): cv.mac_address,
cv.Optional(CONF_WIFI_CHANNEL): cv.int_range(0, 14),
cv.Optional(CONF_WIFI_CHANNEL): validate_channel,
},
key=CONF_MAC_ADDRESS,
)
@ -97,7 +100,7 @@ DEFINE_PEER_CONFIG = cv.maybe_simple_value(
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(): cv.declare_id(ESPNowComponent),
cv.Optional(CONF_WIFI_CHANNEL): cv.int_range(0, 14),
cv.Optional(CONF_WIFI_CHANNEL): validate_channel,
cv.Optional(CONF_AUTO_ADD_PEER, default=False): cv.boolean,
cv.Optional(CONF_USE_SENT_CHECK, default=True): cv.boolean,
cv.Optional(
@ -211,6 +214,25 @@ async def register_protocol(var, config):
cg.add(var.set_protocol_mode(config[CONF_PROTOCOL_MODE]))
def _final_validate(config):
full_config = fv.full_config.get()
if CONF_WIFI_CHANNEL in config and CONF_WIFI in full_config:
raise cv.Invalid(
f"When you have {CONF_WIFI} configured, You can not set the {CONF_WIFI_CHANNEL} variable."
)
if CONF_WIFI_CHANNEL not in config and CONF_WIFI not in full_config:
raise cv.Invalid(
f"When you don't use the {CONF_WIFI} component, You need to set the {CONF_WIFI_CHANNEL} variable."
)
return config
FINAL_VALIDATE_SCHEMA = _final_validate
# ========================================== A C T I O N S ================================================
def validate_peer(value):
if isinstance(value, cv.Lambda):
return cv.returning_lambda(value)
@ -282,7 +304,7 @@ async def send_action(config, action_id, template_arg, args):
{
cv.GenerateID(): cv.use_id(ESPNowComponent),
cv.Required(CONF_MAC_ADDRESS): validate_peer,
cv.Optional(CONF_WIFI_CHANNEL): cv.int_range(0, 14),
cv.Optional(CONF_WIFI_CHANNEL): cv.templatable(validate_channel),
},
key=CONF_MAC_ADDRESS,
),
@ -298,26 +320,32 @@ async def send_action(config, action_id, template_arg, args):
key=CONF_MAC_ADDRESS,
),
)
@automation.register_action(
"espnow.static.peer",
SetStaticPeerAction,
cv.Schema(
{
cv.GenerateID(): cv.use_id(ESPNowComponent),
cv.Required(CONF_PEER_ID): cv.use_id(ESPNowPeer),
cv.Required(CONF_MAC_ADDRESS): validate_peer,
}
),
)
async def peer_action(config, action_id, template_arg, args):
var = cg.new_Pvariable(action_id, template_arg)
await cg.register_parented(var, config[CONF_ID])
if peer_id := config.get(CONF_PEER_ID):
peer = await cg.get_variable(peer_id)
cg.add(var.set_peer_id(peer))
if CONF_WIFI_CHANNEL in config:
cg.add(var.set_wifi_channel(config[CONF_WIFI_CHANNEL]))
template_ = await cg.templatable(config[CONF_WIFI_CHANNEL], args, cg.uint8)
cg.add(var.set_wifi_channel(template_))
await register_peer(var, config, args)
return var
@automation.register_action(
"espnow.channel.set",
SetChannelAction,
cv.maybe_simple_value(
{
cv.GenerateID(): cv.use_id(ESPNowComponent),
cv.Required(CONF_WIFI_CHANNEL): cv.templatable(validate_channel),
},
key=CONF_WIFI_CHANNEL,
),
)
async def channel_action(config, action_id, template_arg, args):
var = cg.new_Pvariable(action_id, template_arg)
await cg.register_parented(var, config[CONF_ID])
template_ = await cg.templatable(config[CONF_WIFI_CHANNEL], args, cg.uint8)
cg.add(var.set_channel(template_))
return var

View File

@ -266,8 +266,8 @@ void ESPNowComponent::set_wifi_channel(uint8_t channel) {
ESPNowPacket packet(ESPNOW_MASS_SEND_ADDR, &channel, 1, ESPNOW_MAIN_PROTOCOL_ID, 251);
this->send(packet);
ESP_LOGD(TAG, "Wifi Channel is changed from %d to %d.", this->wifi_channel_, channel);
this->wifi_channel_ = channel;
}
this->wifi_channel_ = channel;
}
esp_err_t ESPNowComponent::add_peer(uint64_t peer, int8_t channel) {
@ -276,6 +276,11 @@ esp_err_t ESPNowComponent::add_peer(uint64_t peer, int8_t channel) {
esp_now_peer_info_t peer_info = {};
if (this->is_ready()) {
if (peer == this->own_peer_address_) {
ESP_LOGE(TAG, "Tried to peer your self.");
this->mark_failed();
return ESP_ERR_INVALID_MAC;
}
if (esp_now_is_peer_exist((uint8_t *) &peer)) {
esp_now_get_peer((const uint8_t *) &peer, &peer_info);
old_channel = peer_info.channel;
@ -444,8 +449,7 @@ void ESPNowComponent::handle_internal_commands(ESPNowPacket packet) {
case 251:
channel = (int8_t) *packet.get_payload();
this->add_peer(packet.peer, channel);
ESP_LOGI(TAG, "The channel for peer %s. is changed toCommand not used: %d.", packet.get_peer_code().c_str(),
channel);
ESP_LOGI(TAG, "The channel for peer %s is changed to: %d.", packet.get_peer_code().c_str(), channel);
break;
default:
ESP_LOGE(TAG, "Invalid internal ESP-NOW packet. Command not used: %d.", packet.get_command());
@ -453,7 +457,9 @@ void ESPNowComponent::handle_internal_commands(ESPNowPacket packet) {
}
bool ESPNowComponent::send(ESPNowPacket packet) {
if (!this->is_ready()) {
if (packet.peer == this->own_peer_address_) {
ESP_LOGE(TAG, "Tried to peer your self.");
} else if (!this->is_ready()) {
ESP_LOGE(TAG, "Cannot send espnow packet, espnow is not setup yet.");
} else if (this->is_failed()) {
ESP_LOGE(TAG, "Cannot send espnow packet, espnow failed to setup");
@ -482,7 +488,7 @@ bool ESPNowComponent::send(ESPNowPacket packet) {
this->call_on_sent_(packet, err == ESP_OK);
return true;
}
this->mark_failed();
return false;
}
@ -518,7 +524,7 @@ bool ESPNowProtocol::send(uint64_t peer, const uint8_t *data, uint8_t len, uint8
return this->parent_->send(packet);
}
const char *const ChangeChannel::TAG = "espnow.changechannel";
const char *const SetChannel::TAG = "espnow.changechannel";
} // namespace espnow
} // namespace esphome

View File

@ -340,33 +340,18 @@ template<typename... Ts> class DelPeerAction : public Action<Ts...>, public Pare
}
};
template<typename... Ts> class SetStaticPeerAction : public Action<Ts...>, public Parented<ESPNowComponent> {
public:
TEMPLATABLE_VALUE(uint64_t, mac_address);
void set_peer_id(uint64_t &peer_id) { this->peer_id_ = &peer_id; }
void play(Ts... x) override {
uint64_t mac_address = this->mac_address_.value(x...);
*(this->peer_id_) = mac_address;
if (mac_address != 0)
parent_->add_peer(mac_address);
}
protected:
uint64_t *peer_id_;
};
class ChangeChannel {
class SetChannel {
public:
// could be made inline with C++17
static const char *const TAG;
};
template<typename... Ts> class ChangeChannelAction : public Action<Ts...>, public Parented<ESPNowComponent> {
template<typename... Ts> class SetChannelAction : public Action<Ts...>, public Parented<ESPNowComponent> {
public:
TEMPLATABLE_VALUE(int8_t, channel);
void play(Ts... x) override {
#ifdef USE_WIFI
esph_log_e(ChangeChannel::TAG, "Manual changing the channel is not possible with WIFI enabled.");
esph_log_e(SetChannel::TAG, "Manual changing the channel is not possible with WIFI enabled.");
#else
int8_t value = this->channel_.value(x...);
parent_->set_wifi_channel(value);
@ -374,7 +359,7 @@ template<typename... Ts> class ChangeChannelAction : public Action<Ts...>, publi
}
};
/********************************* triggers **************************************/
/********************************* triggers **************************************/
class ESPNowSentTrigger : public Trigger<const ESPNowPacket, bool> {
public:
explicit ESPNowSentTrigger(ESPNowComponent *parent) {

View File

@ -12,29 +12,19 @@ esp32:
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
level: debug
espnow:
auto_add_peer: true
wifi_channel: 1
predefined_peers:
- mac_address: 11:22:33:44:55:66
- mac_address: E8:6B:EA:23:CD:98
on_receive:
- logger.log:
format: "Received: '%s' from '%s' command: %d RSSI: %d"
format: "Received from: %s = '%s' cmd: %d RSSI: %d"
args:
[
packet.get_payload(),
@ -43,15 +33,11 @@ espnow:
packet.rssi,
]
# this works only when esp_idf v5.1.5+ is being used.
on_broadcast:
- command: 123
then:
- logger.log:
format: "Broadcast from: '%s' RSSI: %d: %s"
args:
[
packet.get_peer_code().c_str(),
packet.rssi,
packet.get_payload(),
]
interval:
- interval: 10sec
startup_delay: 20sec
then:
- espnow.send:
mac_address: E8:6B:EA:23:CD:98
payload: "Test 1."
command: 222

View File

@ -26,23 +26,22 @@ esphome:
# To be able to get logs from the device via serial and api.
logger:
level: verbose
level: debug
globals:
- id: hub_address
type: uint64_t
initial_value: "0xE86BEA23CD98"
initial_value: "0x0"
restore_value: yes
espnow:
auto_add_peer: true
wifi_channel: 1
predefined_peers:
- peer_id: keeper
mac_address: E8:6B:EA:23:CD:98
- mac_address: e8:6b:ea:24:22:04
on_receive:
- logger.log:
format: "Received: '%s' from '%s' command: %d RSSI: %d"
format: "Received from: %s = '%s' cmd: %d RSSI: %d"
args:
[
packet.get_payload(),
@ -51,52 +50,15 @@ espnow:
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
startup_delay: 10sec
then:
- espnow.broadcast:
payload: "Broadcast message"
command: 123
- espnow.channel.set: 5
- interval: 5sec
startup_delay: 10sec
then:
- espnow.send:
mac_address: keeper
payload: "Used static keeper value"
command: 222
- espnow.send:
mac_address: E8:6B:EA:23:CD:98
payload: "used fixed mac address"
mac_address: e8:6b:ea:24:22:04
payload: "Test 2."
command: 123
- espnow.send:
# dynamic peer address
mac_address: !lambda return keeper;
payload: "use keeper dynamicly "
command: 62
- espnow.send:
mac_address: !lambda return id(hub_address);
payload: "Using a global numberic value dynamicly"
command: 132
binary_sensor:
- platform: gpio
pin: GPIO39
name: Button
on_click:
- espnow.static.peer:
peer_id: keeper
mac_address: 80:6B:EA:23:CD:87
- espnow.peer.add: 80:6B:EA:23:AA:BB
- espnow.peer.del: 80:6B:EA:23:AA:BB

View File

@ -1,5 +1,5 @@
globals:
- id: hub_address
- id: keeper
type: uint64_t
initial_value: "0xE86BEA23CD98"
restore_value: yes
@ -8,8 +8,7 @@ espnow:
auto_add_peer: true
predefined_peers:
- FF:FF:FF:FF:FF:FF
- peer_id: keeper
mac_address: 11:22:33:44:55:66
- mac_address: 11:22:33:44:55:66
wifi_channel: 2
on_receive:
- logger.log:
@ -40,21 +39,13 @@ interval:
- espnow.broadcast:
payload: "hallo everyone"
command: 123
- espnow.send:
mac_address: keeper
payload: "hallo everyone"
command: 230
- espnow.send:
mac_address: 44:55:66:77:88:33
payload: "hallo everyone"
command: 230
- espnow.send:
# dynamic peer address
mac_address: !lambda return keeper;
payload: "use keeper dynamicly "
command: 62
- espnow.send:
mac_address: !lambda return id(hub_address);
mac_address: !lambda return id(keeper);
payload: "Using a global numberic value dynamicly"
command: 132