12 namespace improv_serial {
14 static const char *
const TAG =
"improv_serial";
26 this->
state_ = improv::STATE_PROVISIONED;
35 optional<uint8_t> byte;
47 #if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \ 48 !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) 50 #endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3 53 uart_get_buffered_data_len(this->
uart_num_, &available);
55 uart_read_bytes(this->
uart_num_, &data, 1, 0);
60 #if defined(CONFIG_ESP_CONSOLE_USB_CDC) && (defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)) 62 #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) 63 if (esp_usb_console_available_for_read()) {
65 if (esp_usb_console_read_available()) {
67 esp_usb_console_read_buf((
char *) &data, 1);
71 #endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 72 #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) 74 if (usb_serial_jtag_read_bytes((
char *) &data, 1, 0)) {
79 #endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32S3 90 this->
hw_serial_->write(data.data(), data.size());
96 #if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \ 97 !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3) 99 #endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3 100 uart_write_bytes(this->
uart_num_, data.data(), data.size());
102 #if defined(CONFIG_ESP_CONSOLE_USB_CDC) && (defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)) 104 const char *msg = (
char *) data.data();
105 esp_usb_console_write_buf(msg, data.size());
108 #endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 109 #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) 111 usb_serial_jtag_write_bytes((
char *) data.data(), data.size(), 20 / portTICK_PERIOD_MS);
113 #endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32S3 124 ESP_LOGV(TAG,
"Improv Serial timeout");
128 while (byte.has_value()) {
138 if (this->
state_ == improv::STATE_PROVISIONING) {
153 std::vector<std::string> urls;
160 std::string webserver_url =
"http://" + ip.str() +
":" +
to_string(USE_WEBSERVER_PORT);
161 urls.push_back(webserver_url);
166 std::vector<uint8_t> data = improv::build_rpc_response(command, urls,
false);
171 std::vector<std::string> infos = {
"ESPHome", ESPHOME_VERSION, ESPHOME_VARIANT,
App.
get_name()};
172 std::vector<uint8_t> data = improv::build_rpc_response(improv::GET_DEVICE_INFO, infos,
false);
179 ESP_LOGV(TAG,
"Improv Serial byte: 0x%02X", byte);
182 return improv::parse_improv_serial_byte(
183 at, byte, raw, [
this](improv::ImprovCommand command) ->
bool {
return this->
parse_improv_payload_(command); },
185 ESP_LOGW(TAG,
"Error decoding Improv payload");
191 switch (command.command) {
192 case improv::WIFI_SETTINGS: {
194 sta.set_ssid(command.ssid);
195 sta.set_password(command.password);
201 ESP_LOGD(TAG,
"Received Improv wifi settings ssid=%s, password=" LOG_SECRET(
"%s"), command.ssid.c_str(),
202 command.password.c_str());
205 this->
set_timeout(
"wifi-connect-timeout", 30000, f);
208 case improv::GET_CURRENT_STATE:
210 if (this->
state_ == improv::STATE_PROVISIONED) {
215 case improv::GET_DEVICE_INFO: {
220 case improv::GET_WIFI_NETWORKS: {
221 std::vector<std::string> networks;
223 for (
auto &scan : results) {
224 if (scan.get_is_hidden())
226 const std::string &ssid = scan.get_ssid();
227 if (std::find(networks.begin(), networks.end(), ssid) != networks.end())
230 std::vector<uint8_t> data = improv::build_rpc_response(
231 improv::GET_WIFI_NETWORKS, {ssid,
str_sprintf(
"%d", scan.get_rssi()), YESNO(scan.get_with_auth())},
false);
233 networks.push_back(ssid);
236 std::vector<uint8_t> data =
237 improv::build_rpc_response(improv::GET_WIFI_NETWORKS, std::vector<std::string>{},
false);
242 ESP_LOGW(TAG,
"Unknown Improv payload");
252 std::vector<uint8_t> data = {
'I',
'M',
'P',
'R',
'O',
'V'};
254 data[6] = IMPROV_SERIAL_VERSION;
260 for (uint8_t d : data)
268 std::vector<uint8_t> data = {
'I',
'M',
'P',
'R',
'O',
'V'};
270 data[6] = IMPROV_SERIAL_VERSION;
275 uint8_t checksum = 0x00;
276 for (uint8_t d : data)
283 std::vector<uint8_t> data = {
'I',
'M',
'P',
'R',
'O',
'V'};
285 data[6] = IMPROV_SERIAL_VERSION;
287 data[8] = response.size();
288 data.insert(data.end(), response.begin(), response.end());
290 uint8_t checksum = 0x00;
291 for (uint8_t d : data)
293 data.push_back(checksum);
299 this->
set_error_(improv::ERROR_UNABLE_TO_CONNECT);
301 ESP_LOGW(TAG,
"Timed out trying to connect to given WiFi network");
void write_data_(std::vector< uint8_t > &data)
bool cancel_timeout(const std::string &name)
Cancel a timeout function.
const std::string & get_password() const
bool parse_improv_payload_(improv::ImprovCommand &command)
void dump_config() override
optional< uint8_t > read_byte_()
void save_wifi_sta(const std::string &ssid, const std::string &password)
std::string get_formatted_next_url_()
const std::vector< WiFiScanResult > & get_scan_result() const
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
bool parse_improv_serial_byte_(uint8_t byte)
void set_state_(improv::State state)
bool is_connected()
Return whether the node is connected to the network (through wifi, eth, ...)
uint32_t IRAM_ATTR HOT millis()
wifi::WiFiAP connecting_sta_
void start_connecting(const WiFiAP &ap, bool two)
std::vector< uint8_t > build_rpc_settings_response_(improv::Command command)
void send_response_(std::vector< uint8_t > &response)
std::string str_sprintf(const char *fmt,...)
void set_error_(improv::Error error)
Application App
Global storage of Application pointer - only one Application can exist.
WiFiComponent * global_wifi_component
const std::string & get_name() const
Get the name of this Application set by pre_setup().
Stream * get_hw_serial() const
std::string to_string(int value)
void on_wifi_connect_timeout_()
void set_sta(const WiFiAP &ap)
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
const std::string & get_ssid() const
std::vector< uint8_t > rx_buffer_
uart_port_t get_uart_num() const
std::vector< uint8_t > build_version_info_()
ImprovSerialComponent * global_improv_serial_component