mirror of https://github.com/esphome/esphome.git
Merge 085eb03ced
into f0ec900e48
This commit is contained in:
commit
836b5b5100
|
@ -326,6 +326,7 @@ esphome/components/sm10bit_base/* @Cossid
|
|||
esphome/components/sm2135/* @BoukeHaarsma23 @dd32 @matika77
|
||||
esphome/components/sm2235/* @Cossid
|
||||
esphome/components/sm2335/* @Cossid
|
||||
esphome/components/smartconfig/* @vinhpn96
|
||||
esphome/components/sml/* @alengwenus
|
||||
esphome/components/smt100/* @piechade
|
||||
esphome/components/sn74hc165/* @jesserockz
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation
|
||||
from esphome.const import CONF_ID, CONF_TRIGGER_ID
|
||||
|
||||
CODEOWNERS = ["@vinhpn96"]
|
||||
DEPENDENCIES = ["wifi"]
|
||||
|
||||
CONF_ON_READY = "on_ready"
|
||||
|
||||
smartconfig_ns = cg.esphome_ns.namespace("smartconfig")
|
||||
SmartConfigComponent = smartconfig_ns.class_("SmartConfigComponent", cg.Component)
|
||||
SmartConfigReadyTrigger = smartconfig_ns.class_(
|
||||
"SmartConfigReadyTrigger", automation.Trigger.template()
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(SmartConfigComponent),
|
||||
cv.Optional(CONF_ON_READY): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SmartConfigReadyTrigger),
|
||||
}
|
||||
),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
cg.add_define("USE_SMARTCONFIG")
|
||||
|
||||
for conf in config.get(CONF_ON_READY, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
|
@ -0,0 +1,183 @@
|
|||
#include "smartconfig_component.h"
|
||||
|
||||
#ifdef USE_ESP32
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_event.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_smartconfig.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
#include "smartconfig.h"
|
||||
#endif
|
||||
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
#if defined(USE_ESP32) || defined(USE_ESP8266)
|
||||
|
||||
namespace esphome {
|
||||
namespace smartconfig {
|
||||
|
||||
#ifdef USE_ESP32
|
||||
#define SC_START_BIT BIT0
|
||||
#define SC_READY_BIT BIT1
|
||||
#define SC_DONE_BIT BIT2
|
||||
#endif
|
||||
|
||||
static const char *const TAG = "smartconfig";
|
||||
static wifi::WiFiAP connecting_sta_; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
#ifdef USE_ESP32
|
||||
static EventGroupHandle_t sce_group = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
static void smartconfig_event_handler(void *arg, esp_event_base_t event_base, int32_t event, void *event_data);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
static bool is_sc_ready{false}; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
static void smartconfig_done(sc_status status, void *pdata);
|
||||
#endif
|
||||
|
||||
static void smartconfig_got_ssid_pwd(void *data);
|
||||
|
||||
SmartConfigComponent::SmartConfigComponent() { global_smartconfig_component = this; }
|
||||
|
||||
float SmartConfigComponent::get_setup_priority() const { return setup_priority::WIFI; }
|
||||
|
||||
void SmartConfigComponent::config() {
|
||||
ESP_LOGD(TAG, "config SmartConfig");
|
||||
|
||||
#if defined(USE_ESP32)
|
||||
sce_group = xEventGroupCreate();
|
||||
esp_err_t err;
|
||||
esp_event_handler_instance_t instance_sc_id;
|
||||
err = esp_event_handler_instance_register(SC_EVENT, ESP_EVENT_ANY_ID, &smartconfig_event_handler, nullptr,
|
||||
&instance_sc_id);
|
||||
ESP_ERROR_CHECK(err);
|
||||
#elif defined(USE_ESP8266)
|
||||
smartconfig_set_type(SC_TYPE_ESPTOUCH);
|
||||
smartconfig_start(smartconfig_done);
|
||||
this->state_ = SmartConfigState::SC_START;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SmartConfigComponent::loop() {
|
||||
#if defined(USE_ESP32)
|
||||
if (sce_group == nullptr) {
|
||||
return;
|
||||
}
|
||||
EventBits_t xbits;
|
||||
xbits = xEventGroupWaitBits(sce_group, SC_START_BIT | SC_READY_BIT | SC_DONE_BIT, true, false, 0);
|
||||
if (xbits & SC_START_BIT) {
|
||||
ESP_LOGD(TAG, "Starting SmartConfig");
|
||||
smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
|
||||
esp_smartconfig_set_type(SC_TYPE_ESPTOUCH);
|
||||
esp_smartconfig_start(&cfg);
|
||||
this->state_ = SmartConfigState::SC_START;
|
||||
}
|
||||
if (xbits & SC_READY_BIT) {
|
||||
ESP_LOGD(TAG, "Smartconfig ready");
|
||||
this->state_ = SmartConfigState::SC_READY;
|
||||
on_smartconfig_ready_.call();
|
||||
}
|
||||
if (xbits & SC_DONE_BIT) {
|
||||
ESP_LOGD(TAG, "Smartconfig over");
|
||||
esp_smartconfig_stop();
|
||||
this->state_ = SmartConfigState::SC_DONE;
|
||||
this->set_timeout("save-wifi", 1000, [] {
|
||||
wifi::global_wifi_component->save_wifi_sta(connecting_sta_.get_ssid(), connecting_sta_.get_password());
|
||||
});
|
||||
}
|
||||
#elif defined(USE_ESP8266)
|
||||
if (is_sc_ready && (this->state_ != SmartConfigState::SC_READY)) {
|
||||
this->state_ = SmartConfigState::SC_READY;
|
||||
on_smartconfig_ready_.call();
|
||||
} else if (!is_sc_ready && (this->state_ == SmartConfigState::SC_READY) &&
|
||||
wifi::global_wifi_component->is_connected()) {
|
||||
this->state_ = SmartConfigState::SC_DONE;
|
||||
this->set_timeout("save-wifi", 1000, [] {
|
||||
wifi::global_wifi_component->save_wifi_sta(connecting_sta_.get_ssid(), connecting_sta_.get_password());
|
||||
});
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_ESP32
|
||||
void SmartConfigComponent::start() {
|
||||
if (this->state_ == SmartConfigState::SC_IDLE) {
|
||||
xEventGroupSetBits(sce_group, SC_START_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
void smartconfig_event_handler(void *arg, esp_event_base_t event_base, int32_t event, void *event_data) {
|
||||
if (event_base == SC_EVENT && event == SC_EVENT_SCAN_DONE) {
|
||||
ESP_LOGD(TAG, "SC_EVENT_SCAN_DONE");
|
||||
xEventGroupSetBits(sce_group, SC_READY_BIT);
|
||||
} else if (event_base == SC_EVENT && event == SC_EVENT_FOUND_CHANNEL) {
|
||||
ESP_LOGD(TAG, "Found channel");
|
||||
} else if (event_base == SC_EVENT && event == SC_EVENT_GOT_SSID_PSWD) {
|
||||
smartconfig_got_ssid_pwd(event_data);
|
||||
} else if (event_base == SC_EVENT && event == SC_EVENT_SEND_ACK_DONE) {
|
||||
xEventGroupSetBits(sce_group, SC_DONE_BIT);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void smartconfig_got_ssid_pwd(void *data) {
|
||||
#if defined(USE_ESP32)
|
||||
smartconfig_event_got_ssid_pswd_t *sta_conf = (smartconfig_event_got_ssid_pswd_t *) data;
|
||||
#elif defined(USE_ESP8266)
|
||||
struct station_config *sta_conf = (struct station_config *) data;
|
||||
#endif
|
||||
std::string ssid((char *) sta_conf->ssid);
|
||||
std::string password((char *) sta_conf->password);
|
||||
connecting_sta_.set_ssid(ssid);
|
||||
connecting_sta_.set_password(password);
|
||||
|
||||
wifi::global_wifi_component->set_sta(connecting_sta_);
|
||||
wifi::global_wifi_component->start_scanning();
|
||||
ESP_LOGD(TAG, "Received smartconfig wifi settings ssid=%s, password=" LOG_SECRET("%s"), ssid.c_str(),
|
||||
password.c_str());
|
||||
}
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
void smartconfig_done(sc_status status, void *pdata) {
|
||||
switch (status) {
|
||||
case SC_STATUS_WAIT:
|
||||
ESP_LOGD(TAG, "SC_STATUS_WAIT");
|
||||
break;
|
||||
case SC_STATUS_FIND_CHANNEL:
|
||||
ESP_LOGD(TAG, "SC_STATUS_FIND_CHANNEL");
|
||||
is_sc_ready = true;
|
||||
break;
|
||||
case SC_STATUS_GETTING_SSID_PSWD:
|
||||
ESP_LOGD(TAG, "SC_STATUS_GETTING_SSID_PSWD");
|
||||
break;
|
||||
case SC_STATUS_LINK:
|
||||
ESP_LOGD(TAG, "SC_STATUS_LINK");
|
||||
smartconfig_got_ssid_pwd(pdata);
|
||||
break;
|
||||
case SC_STATUS_LINK_OVER:
|
||||
ESP_LOGD(TAG, "SC_STATUS_LINK_OVER");
|
||||
smartconfig_stop();
|
||||
is_sc_ready = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
SmartConfigComponent *global_smartconfig_component = // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
nullptr;
|
||||
|
||||
SmartConfigReadyTrigger::SmartConfigReadyTrigger(SmartConfigComponent *&sc_component) {
|
||||
sc_component->add_on_ready([this]() {
|
||||
ESP_LOGD(TAG, "Smartconfig is ready");
|
||||
this->trigger();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace smartconfig
|
||||
} // namespace esphome
|
||||
|
||||
#endif
|
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/components/wifi/wifi_component.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
#if defined(USE_ESP32) || defined(USE_ESP8266)
|
||||
|
||||
namespace esphome {
|
||||
namespace smartconfig {
|
||||
|
||||
using on_smartconfig_ready_cb_t = std::function<void()>;
|
||||
|
||||
class SmartConfigComponent : public Component {
|
||||
public:
|
||||
enum class SmartConfigState {
|
||||
SC_IDLE,
|
||||
SC_START,
|
||||
SC_READY,
|
||||
SC_DONE,
|
||||
};
|
||||
SmartConfigComponent();
|
||||
|
||||
void loop() override;
|
||||
#ifdef USE_ESP32
|
||||
void start();
|
||||
#endif
|
||||
|
||||
float get_setup_priority() const override;
|
||||
void config();
|
||||
void add_on_ready(on_smartconfig_ready_cb_t callback) { on_smartconfig_ready_.add(std::move(callback)); }
|
||||
|
||||
protected:
|
||||
CallbackManager<void()> on_smartconfig_ready_;
|
||||
SmartConfigState state_{SmartConfigState::SC_IDLE};
|
||||
};
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
extern SmartConfigComponent *global_smartconfig_component;
|
||||
|
||||
class SmartConfigReadyTrigger : public Trigger<> {
|
||||
public:
|
||||
explicit SmartConfigReadyTrigger(SmartConfigComponent *&sc_component);
|
||||
};
|
||||
|
||||
} // namespace smartconfig
|
||||
} // namespace esphome
|
||||
|
||||
#endif
|
|
@ -177,7 +177,8 @@ def final_validate(config):
|
|||
has_ap = CONF_AP in config
|
||||
has_improv = "esp32_improv" in fv.full_config.get()
|
||||
has_improv_serial = "improv_serial" in fv.full_config.get()
|
||||
if not (has_sta or has_ap or has_improv or has_improv_serial):
|
||||
has_smartconfig = "smartconfig" in fv.full_config.get()
|
||||
if not (has_sta or has_ap or has_improv or has_improv_serial or has_smartconfig):
|
||||
raise cv.Invalid(
|
||||
"Please specify at least an SSID or an Access Point to create."
|
||||
)
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
#include "esphome/components/esp32_improv/esp32_improv_component.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_SMARTCONFIG
|
||||
#include "esphome/components/smartconfig/smartconfig_component.h"
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace wifi {
|
||||
|
||||
|
@ -111,6 +115,12 @@ void WiFiComponent::start() {
|
|||
if (this->wifi_mode_(true, {}))
|
||||
esp32_improv::global_improv_component->start();
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SMARTCONFIG
|
||||
if (!this->has_sta() && smartconfig::global_smartconfig_component != nullptr) {
|
||||
if (this->wifi_mode_(true, {}))
|
||||
smartconfig::global_smartconfig_component->config();
|
||||
}
|
||||
#endif
|
||||
this->wifi_apply_hostname_();
|
||||
}
|
||||
|
@ -192,6 +202,11 @@ void WiFiComponent::loop() {
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef USE_SMARTCONFIG
|
||||
if ((smartconfig::global_smartconfig_component != nullptr) && (!this->is_connected())) {
|
||||
this->wifi_mode_(true, {});
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!this->has_ap() && this->reboot_timeout_ != 0) {
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/util.h"
|
||||
|
||||
#ifdef USE_SMARTCONFIG
|
||||
#include "esphome/components/smartconfig/smartconfig_component.h"
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace wifi {
|
||||
|
||||
|
@ -451,6 +455,10 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_
|
|||
case ESPHOME_EVENT_ID_WIFI_STA_START: {
|
||||
ESP_LOGV(TAG, "Event: WiFi STA start");
|
||||
tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, App.get_name().c_str());
|
||||
#ifdef USE_SMARTCONFIG
|
||||
if (!this->has_sta())
|
||||
smartconfig::global_smartconfig_component->start();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case ESPHOME_EVENT_ID_WIFI_STA_STOP: {
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/util.h"
|
||||
|
||||
#ifdef USE_SMARTCONFIG
|
||||
#include "esphome/components/smartconfig/smartconfig_component.h"
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace wifi {
|
||||
|
||||
|
@ -628,6 +632,10 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) {
|
|||
s_sta_started = true;
|
||||
// re-apply power save mode
|
||||
wifi_apply_power_save_();
|
||||
#ifdef USE_SMARTCONFIG
|
||||
if (!this->has_sta())
|
||||
smartconfig::global_smartconfig_component->start();
|
||||
#endif
|
||||
|
||||
} else if (data->event_base == WIFI_EVENT && data->event_id == WIFI_EVENT_STA_STOP) {
|
||||
ESP_LOGV(TAG, "Event: WiFi STA stop");
|
||||
|
|
|
@ -22,6 +22,8 @@ wifi:
|
|||
gateway: 192.168.1.1
|
||||
subnet: 255.255.255.0
|
||||
|
||||
smartconfig:
|
||||
|
||||
network:
|
||||
enable_ipv6: true
|
||||
|
||||
|
|
Loading…
Reference in New Issue