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

Merge branch 'dev' into nvds-new-espnow

This commit is contained in:
NP v/d Spek 2024-11-24 23:47:28 +01:00 committed by GitHub
commit 2593366a1b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 135 additions and 5 deletions

View File

@ -58,7 +58,7 @@ class BinarySensor : public EntityBase, public EntityBase_DeviceClass {
void publish_initial_state(bool state); void publish_initial_state(bool state);
/// The current reported state of the binary sensor. /// The current reported state of the binary sensor.
bool state; bool state{false};
void add_filter(Filter *filter); void add_filter(Filter *filter);
void add_filters(const std::vector<Filter *> &filters); void add_filters(const std::vector<Filter *> &filters);

View File

@ -68,8 +68,6 @@ IsActiveCondition = display_menu_base_ns.class_(
"IsActiveCondition", automation.Condition "IsActiveCondition", automation.Condition
) )
MULTI_CONF = True
MenuItemType = display_menu_base_ns.enum("MenuItemType") MenuItemType = display_menu_base_ns.enum("MenuItemType")
MENU_ITEM_TYPES = { MENU_ITEM_TYPES = {

View File

@ -36,6 +36,8 @@ CODEOWNERS = ["@MrMDavidson"]
AUTO_LOAD = ["display_menu_base"] AUTO_LOAD = ["display_menu_base"]
MULTI_CONF = True
CONFIG_SCHEMA = DISPLAY_MENU_BASE_SCHEMA.extend( CONFIG_SCHEMA = DISPLAY_MENU_BASE_SCHEMA.extend(
cv.Schema( cv.Schema(
{ {

View File

@ -6,7 +6,7 @@
namespace esphome { namespace esphome {
namespace matrix_keypad { namespace matrix_keypad {
class MatrixKeypadBinarySensor : public MatrixKeypadListener, public binary_sensor::BinarySensor { class MatrixKeypadBinarySensor : public MatrixKeypadListener, public binary_sensor::BinarySensorInitiallyOff {
public: public:
MatrixKeypadBinarySensor(uint8_t key) : has_key_(true), key_(key){}; MatrixKeypadBinarySensor(uint8_t key) : has_key_(true), key_(key){};
MatrixKeypadBinarySensor(const char *key) : has_key_(true), key_((uint8_t) key[0]){}; MatrixKeypadBinarySensor(const char *key) : has_key_(true), key_((uint8_t) key[0]){};

View File

@ -163,7 +163,7 @@ CONFIG_SCHEMA = cv.All(
), ),
cv.Optional(CONF_ON_OFFLINE): automation.validate_automation( cv.Optional(CONF_ON_OFFLINE): automation.validate_automation(
{ {
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ModbusOnlineTrigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ModbusOfflineTrigger),
} }
), ),
} }

View File

@ -6,6 +6,8 @@ from esphome.const import (
ENTITY_CATEGORY_DIAGNOSTIC, ENTITY_CATEGORY_DIAGNOSTIC,
) )
DEPENDENCIES = ["network"]
status_ns = cg.esphome_ns.namespace("status") status_ns = cg.esphome_ns.namespace("status")
StatusBinarySensor = status_ns.class_( StatusBinarySensor = status_ns.class_(
"StatusBinarySensor", binary_sensor.BinarySensor, cg.Component "StatusBinarySensor", binary_sensor.BinarySensor, cg.Component

View File

@ -27,6 +27,7 @@ from esphome.const import (
CONF_NETWORKS, CONF_NETWORKS,
CONF_ON_CONNECT, CONF_ON_CONNECT,
CONF_ON_DISCONNECT, CONF_ON_DISCONNECT,
CONF_ON_ERROR,
CONF_PASSWORD, CONF_PASSWORD,
CONF_POWER_SAVE_MODE, CONF_POWER_SAVE_MODE,
CONF_PRIORITY, CONF_PRIORITY,
@ -34,6 +35,7 @@ from esphome.const import (
CONF_SSID, CONF_SSID,
CONF_STATIC_IP, CONF_STATIC_IP,
CONF_SUBNET, CONF_SUBNET,
CONF_TIMEOUT,
CONF_TTLS_PHASE_2, CONF_TTLS_PHASE_2,
CONF_USE_ADDRESS, CONF_USE_ADDRESS,
CONF_USERNAME, CONF_USERNAME,
@ -46,6 +48,7 @@ from . import wpa2_eap
AUTO_LOAD = ["network"] AUTO_LOAD = ["network"]
NO_WIFI_VARIANTS = [const.VARIANT_ESP32H2] NO_WIFI_VARIANTS = [const.VARIANT_ESP32H2]
CONF_SAVE = "save"
wifi_ns = cg.esphome_ns.namespace("wifi") wifi_ns = cg.esphome_ns.namespace("wifi")
EAPAuth = wifi_ns.struct("EAPAuth") EAPAuth = wifi_ns.struct("EAPAuth")
@ -63,6 +66,9 @@ WiFiConnectedCondition = wifi_ns.class_("WiFiConnectedCondition", Condition)
WiFiEnabledCondition = wifi_ns.class_("WiFiEnabledCondition", Condition) WiFiEnabledCondition = wifi_ns.class_("WiFiEnabledCondition", Condition)
WiFiEnableAction = wifi_ns.class_("WiFiEnableAction", automation.Action) WiFiEnableAction = wifi_ns.class_("WiFiEnableAction", automation.Action)
WiFiDisableAction = wifi_ns.class_("WiFiDisableAction", automation.Action) WiFiDisableAction = wifi_ns.class_("WiFiDisableAction", automation.Action)
WiFiConfigureAction = wifi_ns.class_(
"WiFiConfigureAction", automation.Action, cg.Component
)
def validate_password(value): def validate_password(value):
@ -483,3 +489,39 @@ async def wifi_enable_to_code(config, action_id, template_arg, args):
@automation.register_action("wifi.disable", WiFiDisableAction, cv.Schema({})) @automation.register_action("wifi.disable", WiFiDisableAction, cv.Schema({}))
async def wifi_disable_to_code(config, action_id, template_arg, args): async def wifi_disable_to_code(config, action_id, template_arg, args):
return cg.new_Pvariable(action_id, template_arg) return cg.new_Pvariable(action_id, template_arg)
@automation.register_action(
"wifi.configure",
WiFiConfigureAction,
cv.Schema(
{
cv.Required(CONF_SSID): cv.templatable(cv.ssid),
cv.Required(CONF_PASSWORD): cv.templatable(validate_password),
cv.Optional(CONF_SAVE, default=True): cv.templatable(cv.boolean),
cv.Optional(CONF_TIMEOUT, default="30000ms"): cv.templatable(
cv.positive_time_period_milliseconds
),
cv.Optional(CONF_ON_CONNECT): automation.validate_automation(single=True),
cv.Optional(CONF_ON_ERROR): automation.validate_automation(single=True),
}
),
)
async def wifi_set_sta_to_code(config, action_id, template_arg, args):
var = cg.new_Pvariable(action_id, template_arg)
ssid = await cg.templatable(config[CONF_SSID], args, cg.std_string)
password = await cg.templatable(config[CONF_PASSWORD], args, cg.std_string)
save = await cg.templatable(config[CONF_SAVE], args, cg.bool_)
timeout = await cg.templatable(config.get(CONF_TIMEOUT), args, cg.uint32)
cg.add(var.set_ssid(ssid))
cg.add(var.set_password(password))
cg.add(var.set_save(save))
cg.add(var.set_connection_timeout(timeout))
if on_connect_config := config.get(CONF_ON_CONNECT):
await automation.build_automation(
var.get_connect_trigger(), [], on_connect_config
)
if on_error_config := config.get(CONF_ON_ERROR):
await automation.build_automation(var.get_error_trigger(), [], on_error_config)
await cg.register_component(var, config)
return var

View File

@ -209,6 +209,7 @@ class WiFiComponent : public Component {
WiFiComponent(); WiFiComponent();
void set_sta(const WiFiAP &ap); void set_sta(const WiFiAP &ap);
WiFiAP get_sta() { return this->selected_ap_; }
void add_sta(const WiFiAP &ap); void add_sta(const WiFiAP &ap);
void clear_sta(); void clear_sta();
@ -443,6 +444,84 @@ template<typename... Ts> class WiFiDisableAction : public Action<Ts...> {
void play(Ts... x) override { global_wifi_component->disable(); } void play(Ts... x) override { global_wifi_component->disable(); }
}; };
template<typename... Ts> class WiFiConfigureAction : public Action<Ts...>, public Component {
public:
TEMPLATABLE_VALUE(std::string, ssid)
TEMPLATABLE_VALUE(std::string, password)
TEMPLATABLE_VALUE(bool, save)
TEMPLATABLE_VALUE(uint32_t, connection_timeout)
void play(Ts... x) override {
auto ssid = this->ssid_.value(x...);
auto password = this->password_.value(x...);
// Avoid multiple calls
if (this->connecting_)
return;
// If already connected to the same AP, do nothing
if (global_wifi_component->wifi_ssid() == ssid) {
// Callback to notify the user that the connection was successful
this->connect_trigger_->trigger();
return;
}
// Create a new WiFiAP object with the new SSID and password
this->new_sta_.set_ssid(ssid);
this->new_sta_.set_password(password);
// Save the current STA
this->old_sta_ = global_wifi_component->get_sta();
// Disable WiFi
global_wifi_component->disable();
// Set the state to connecting
this->connecting_ = true;
// Store the new STA so once the WiFi is enabled, it will connect to it
// This is necessary because the WiFiComponent will raise an error and fallback to the saved STA
// if trying to connect to a new STA while already connected to another one
if (this->save_.value(x...)) {
global_wifi_component->save_wifi_sta(new_sta_.get_ssid(), new_sta_.get_password());
} else {
global_wifi_component->set_sta(new_sta_);
}
// Enable WiFi
global_wifi_component->enable();
// Set timeout for the connection
this->set_timeout("wifi-connect-timeout", this->connection_timeout_.value(x...), [this]() {
this->connecting_ = false;
// If the timeout is reached, stop connecting and revert to the old AP
global_wifi_component->disable();
global_wifi_component->save_wifi_sta(old_sta_.get_ssid(), old_sta_.get_password());
global_wifi_component->enable();
// Callback to notify the user that the connection failed
this->error_trigger_->trigger();
});
}
Trigger<> *get_connect_trigger() const { return this->connect_trigger_; }
Trigger<> *get_error_trigger() const { return this->error_trigger_; }
void loop() override {
if (!this->connecting_)
return;
if (global_wifi_component->is_connected()) {
// The WiFi is connected, stop the timeout and reset the connecting flag
this->cancel_timeout("wifi-connect-timeout");
this->connecting_ = false;
if (global_wifi_component->wifi_ssid() == this->new_sta_.get_ssid()) {
// Callback to notify the user that the connection was successful
this->connect_trigger_->trigger();
} else {
// Callback to notify the user that the connection failed
this->error_trigger_->trigger();
}
}
}
protected:
bool connecting_{false};
WiFiAP new_sta_;
WiFiAP old_sta_;
Trigger<> *connect_trigger_{new Trigger<>()};
Trigger<> *error_trigger_{new Trigger<>()};
};
} // namespace wifi } // namespace wifi
} // namespace esphome } // namespace esphome
#endif #endif

View File

@ -3,6 +3,13 @@ esphome:
then: then:
- wifi.disable - wifi.disable
- wifi.enable - wifi.enable
- wifi.configure:
ssid: MySSID
password: password1
on_connect:
- logger.log: "Connected to WiFi!"
on_error:
- logger.log: "Failed to connect to WiFi!"
wifi: wifi:
ssid: MySSID ssid: MySSID