12namespace improv_serial {
14static const char *
const TAG =
"improv_serial";
20#elif defined(USE_ARDUINO)
25 this->
state_ = improv::STATE_PROVISIONED;
40#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
41 !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3)
46 uart_get_buffered_data_len(this->
uart_num_, &available);
48 uart_read_bytes(this->
uart_num_, &data, 1, 0);
53#if defined(USE_LOGGER_USB_CDC) && defined(CONFIG_ESP_CONSOLE_USB_CDC)
55 if (esp_usb_console_available_for_read()) {
56 esp_usb_console_read_buf((
char *) &data, 1);
61#ifdef USE_LOGGER_USB_SERIAL_JTAG
63 if (usb_serial_jtag_read_bytes((
char *) &data, 1, 0)) {
72#elif defined(USE_ARDUINO)
87#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
88 !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3)
91 uart_write_bytes(this->
uart_num_, data.data(), data.size());
93#if defined(USE_LOGGER_USB_CDC) && defined(CONFIG_ESP_CONSOLE_USB_CDC)
95 const char *msg = (
char *) data.data();
96 esp_usb_console_write_buf(msg, data.size());
100#ifdef USE_LOGGER_USB_SERIAL_JTAG
102 usb_serial_jtag_write_bytes((
char *) data.data(), data.size(), 20 / portTICK_PERIOD_MS);
104 usb_serial_jtag_ll_txfifo_flush();
110#elif defined(USE_ARDUINO)
111 this->
hw_serial_->write(data.data(), data.size());
119 ESP_LOGV(TAG,
"Improv Serial timeout");
123 while (
byte.has_value()) {
133 if (this->
state_ == improv::STATE_PROVISIONING) {
136 this->connecting_sta_.get_password());
148 std::vector<std::string> urls;
155 std::string webserver_url =
"http://" + ip.str() +
":" + to_string(USE_WEBSERVER_PORT);
156 urls.push_back(webserver_url);
161 std::vector<uint8_t> data = improv::build_rpc_response(command, urls,
false);
166#ifdef ESPHOME_PROJECT_NAME
167 std::vector<std::string> infos = {ESPHOME_PROJECT_NAME, ESPHOME_PROJECT_VERSION, ESPHOME_VARIANT,
App.
get_name()};
169 std::vector<std::string> infos = {
"ESPHome", ESPHOME_VERSION, ESPHOME_VARIANT,
App.
get_name()};
171 std::vector<uint8_t> data = improv::build_rpc_response(improv::GET_DEVICE_INFO, infos,
false);
178 ESP_LOGV(TAG,
"Improv Serial byte: 0x%02X",
byte);
181 return improv::parse_improv_serial_byte(
183 [
this](improv::Error error) ->
void {
184 ESP_LOGW(TAG,
"Error decoding Improv payload");
190 switch (command.command) {
191 case improv::WIFI_SETTINGS: {
194 sta.set_password(command.password);
200 ESP_LOGD(TAG,
"Received Improv wifi settings ssid=%s, password=" LOG_SECRET(
"%s"), command.ssid.c_str(),
201 command.password.c_str());
204 this->
set_timeout(
"wifi-connect-timeout", 30000, f);
207 case improv::GET_CURRENT_STATE:
209 if (this->
state_ == improv::STATE_PROVISIONED) {
214 case improv::GET_DEVICE_INFO: {
219 case improv::GET_WIFI_NETWORKS: {
220 std::vector<std::string> networks;
222 for (
auto &scan : results) {
223 if (scan.get_is_hidden())
225 const std::string &ssid = scan.get_ssid();
226 if (std::find(networks.begin(), networks.end(), ssid) != networks.end())
229 std::vector<uint8_t> data = improv::build_rpc_response(
230 improv::GET_WIFI_NETWORKS, {ssid,
str_sprintf(
"%d", scan.get_rssi()), YESNO(scan.get_with_auth())},
false);
232 networks.push_back(ssid);
235 std::vector<uint8_t> data =
236 improv::build_rpc_response(improv::GET_WIFI_NETWORKS, std::vector<std::string>{},
false);
241 ESP_LOGW(TAG,
"Unknown Improv payload");
251 std::vector<uint8_t> data = {
'I',
'M',
'P',
'R',
'O',
'V'};
253 data[6] = IMPROV_SERIAL_VERSION;
259 for (uint8_t d : data)
267 std::vector<uint8_t> data = {
'I',
'M',
'P',
'R',
'O',
'V'};
269 data[6] = IMPROV_SERIAL_VERSION;
275 for (uint8_t d : data)
282 std::vector<uint8_t> data = {
'I',
'M',
'P',
'R',
'O',
'V'};
284 data[6] = IMPROV_SERIAL_VERSION;
286 data[8] = response.size();
287 data.insert(data.end(), response.begin(), response.end());
290 for (uint8_t d : data)
298 this->
set_error_(improv::ERROR_UNABLE_TO_CONNECT);
300 ESP_LOGW(TAG,
"Timed out trying to connect to given WiFi network");
const std::string & get_name() const
Get the name of this Application set by pre_setup().
bool cancel_timeout(const std::string &name)
Cancel a timeout function.
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
std::string get_formatted_next_url_()
std::vector< uint8_t > rx_buffer_
std::vector< uint8_t > build_rpc_settings_response_(improv::Command command)
void set_state_(improv::State state)
wifi::WiFiAP connecting_sta_
void on_wifi_connect_timeout_()
void send_response_(std::vector< uint8_t > &response)
void write_data_(std::vector< uint8_t > &data)
void dump_config() override
bool parse_improv_serial_byte_(uint8_t byte)
optional< uint8_t > read_byte_()
std::vector< uint8_t > build_version_info_()
bool parse_improv_payload_(improv::ImprovCommand &command)
void set_error_(improv::Error error)
Stream * get_hw_serial() const
uart_port_t get_uart_num() const
const std::string & get_ssid() const
void set_ssid(const std::string &ssid)
void set_sta(const WiFiAP &ap)
void save_wifi_sta(const std::string &ssid, const std::string &password)
void start_connecting(const WiFiAP &ap, bool two)
const std::vector< WiFiScanResult > & get_scan_result() const
ImprovSerialComponent * global_improv_serial_component
@ UART_SELECTION_USB_SERIAL_JTAG
WiFiComponent * global_wifi_component
Providing packet encoding functions for exchanging data with a remote host.
std::string str_sprintf(const char *fmt,...)
void IRAM_ATTR HOT delay(uint32_t ms)
uint32_t IRAM_ATTR HOT millis()
Application App
Global storage of Application pointer - only one Application can exist.