From b2f8bc56385344d2fc77e4dda7f611bbda5cf537 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 13 May 2017 10:26:59 +0800 Subject: [PATCH] esp32: multi ap slots --- lib/libwebsockets.c | 8 + lib/libwebsockets.h | 11 +- lib/lws-plat-esp32.c | 295 ++++++++++++++++++++++++------ lib/private-libwebsockets.h | 1 + lib/ssl.c | 10 + plugins/protocol_esp32_lws_scan.c | 104 +++++++---- 6 files changed, 342 insertions(+), 87 deletions(-) diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index 7750429f..b69a4ef2 100755 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -3144,6 +3144,8 @@ lws_stats_log_dump(struct lws_context *context) lwsl_notice("LWSSTATS_C_WRITEABLE_CB: %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_WRITEABLE_CB)); lwsl_notice("LWSSTATS_C_SSL_CONNECTIONS_FAILED: %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_SSL_CONNECTIONS_FAILED)); lwsl_notice("LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED: %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED)); + lwsl_notice("LWSSTATS_C_SSL_CONNS_HAD_RX: %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_SSL_CONNS_HAD_RX)); + lwsl_notice("LWSSTATS_C_TIMEOUTS: %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_TIMEOUTS)); lwsl_notice("LWSSTATS_C_SERVICE_ENTRY: %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_SERVICE_ENTRY)); lwsl_notice("LWSSTATS_B_READ: %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_B_READ)); @@ -3154,6 +3156,12 @@ lws_stats_log_dump(struct lws_context *context) lwsl_notice(" Avg accept delay: %8llums\n", (unsigned long long)(lws_stats_get(context, LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY) / lws_stats_get(context, LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED)) / 1000); + lwsl_notice("LWSSTATS_MS_SSL_RX_DELAY: %8llums\n", (unsigned long long)lws_stats_get(context, LWSSTATS_MS_SSL_RX_DELAY) / 1000); + if (lws_stats_get(context, LWSSTATS_C_SSL_CONNS_HAD_RX)) + lwsl_notice(" Avg accept-rx delay: %8llums\n", + (unsigned long long)(lws_stats_get(context, LWSSTATS_MS_SSL_RX_DELAY) / + lws_stats_get(context, LWSSTATS_C_SSL_CONNS_HAD_RX)) / 1000); + lwsl_notice("LWSSTATS_MS_WRITABLE_DELAY: %8lluus\n", (unsigned long long)lws_stats_get(context, LWSSTATS_MS_WRITABLE_DELAY)); lwsl_notice("LWSSTATS_MS_WORST_WRITABLE_DELAY: %8lluus\n", diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 679dddc8..d40268fd 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -555,8 +555,7 @@ lws_esp32_identify_physical_device(void); /* lws-plat-esp32 provides these */ -extern void (*lws_cb_scan_done)(void *); -extern void *lws_cb_scan_done_arg; +typedef void (*lws_cb_scan_done)(uint16_t count, wifi_ap_record_t *recs, void *arg); struct lws_esp32 { char sta_ip[16]; @@ -567,11 +566,15 @@ struct lws_esp32 { char model[16]; char group[16]; char role[16]; + char ssid[4][16]; + char password[4][32]; char active_ssid[32]; char access_pw[16]; mdns_server_t *mdns; char region; char inet; + lws_cb_scan_done scan_consumer; + void *scan_consumer_arg; }; struct lws_esp32_image { @@ -598,6 +601,8 @@ extern struct lws_context * lws_esp32_init(struct lws_context_creation_info *); extern int lws_esp32_wlan_nvs_get(int retry); +extern esp_err_t +lws_nvs_set_str(nvs_handle handle, const char* key, const char* value); extern void lws_esp32_restart_guided(uint32_t type); extern const esp_partition_t * @@ -4808,6 +4813,7 @@ enum { LWSSTATS_C_WRITEABLE_CB, /**< count of writable callbacks */ LWSSTATS_C_SSL_CONNECTIONS_FAILED, /**< count of failed SSL connections */ LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED, /**< count of accepted SSL connections */ + LWSSTATS_C_SSL_CONNS_HAD_RX, /**< count of accepted SSL conns that have had some RX */ LWSSTATS_C_TIMEOUTS, /**< count of timed-out connections */ LWSSTATS_C_SERVICE_ENTRY, /**< count of entries to lws service loop */ LWSSTATS_B_READ, /**< aggregate bytes read */ @@ -4816,6 +4822,7 @@ enum { LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY, /**< aggregate delay in accepting connection */ LWSSTATS_MS_WRITABLE_DELAY, /**< aggregate delay between asking for writable and getting cb */ LWSSTATS_MS_WORST_WRITABLE_DELAY, /**< single worst delay between asking for writable and getting cb */ + LWSSTATS_MS_SSL_RX_DELAY, /**< aggregate delay between ssl accept complete and first RX */ /* Add new things just above here ---^ * This is part of the ABI, don't needlessly break compatibility */ diff --git a/lib/lws-plat-esp32.c b/lib/lws-plat-esp32.c index 8294fefa..c8eaf420 100644 --- a/lib/lws-plat-esp32.c +++ b/lib/lws-plat-esp32.c @@ -625,16 +625,34 @@ enum lws_gapss { * don't get an IP within a timeout and retries, * blacklist it and go back */ + LWS_GAPSS_STAT_HAPPY, +}; + +static const char *gapss_str[] = { + "LWS_GAPSS_INITIAL", + "LWS_GAPSS_SCAN", + "LWS_GAPSS_AP", + "LWS_GAPSS_AP_SCAN", + "LWS_GAPSS_STAT_GRP_AP", + "LWS_GAPSS_STAT_GRP_AP_SCAN", + "LWS_GAPSS_STAT", + "LWS_GAPSS_STAT_HAPPY", }; static romfs_t lws_esp32_romfs; -static TimerHandle_t leds_timer; -//static enum lws_gapss gapss = LWS_GAPSS_INITIAL; +static TimerHandle_t leds_timer, scan_timer; +static enum lws_gapss gapss = LWS_GAPSS_INITIAL; struct esp32_file { const struct inode *i; }; +static void lws_gapss_to(enum lws_gapss to) +{ + lwsl_notice("gapss from %s to %s\n", gapss_str[gapss], gapss_str[to]); + gapss = to; +} + uint32_t lws_esp32_get_reboot_type(void) { uint32_t *p = (uint32_t *)LWS_MAGIC_REBOOT_TYPE_ADS, val = *p; @@ -674,17 +692,178 @@ void lws_esp32_restart_guided(uint32_t type) esp_restart(); } +/* + * esp-idf goes crazy with zero length str nvs. Use this as a workaround + * to delete the key in that case. + */ + +esp_err_t lws_nvs_set_str(nvs_handle handle, const char* key, const char* value) +{ + if (*value) + return nvs_set_str(handle, key, value); + + return nvs_erase_key(handle, key); +} + +static wifi_scan_config_t scan_config = { + .ssid = 0, + .bssid = 0, + .channel = 0, + .show_hidden = true +}; + +static char scan_ongoing = 0i, scan_timer_exists = 0; +static int try_slot = -1; + +static wifi_config_t config = { + .ap = { + .channel = 6, + .authmode = WIFI_AUTH_OPEN, + .max_connection = 1, + } }, sta_config = { + .sta = { + .bssid_set = 0, + } }; + +static void lws_esp32_scan_timer_cb(TimerHandle_t th) +{ + int n; + + scan_ongoing = 0; + n = esp_wifi_scan_start(&scan_config, false); + if (n != ESP_OK) + lwsl_err("scan start failed %d\n", n); +} + + +static int +start_scan() +{ + /* if no APs configured, no point... */ + + if (!lws_esp32.ssid[0][0] && + !lws_esp32.ssid[1][0] && + !lws_esp32.ssid[2][0] && + !lws_esp32.ssid[3][0]) + return 0; + + if (scan_timer_exists && !scan_ongoing) { + scan_ongoing = 1; + xTimerStart(scan_timer, 0); + } else + lwsl_notice("%s: ignoring, no scan timer\n", __func__); + + return 0; +} + + + +static void +end_scan() +{ + wifi_ap_record_t ap_records[10]; + uint16_t count_ap_records; + int n, m; + + count_ap_records = ARRAY_SIZE(ap_records); + if (esp_wifi_scan_get_ap_records(&count_ap_records, ap_records) != ESP_OK) { + lwsl_err("%s: failed\n", __func__); + return; + } + + if (!count_ap_records) + goto passthru; + + if (gapss != LWS_GAPSS_SCAN) { + lwsl_notice("ignoring scan as gapss %s\n", gapss_str[gapss]); + goto passthru; + } + + /* no point if no APs set up */ + if (!lws_esp32.ssid[0][0] && + !lws_esp32.ssid[1][0] && + !lws_esp32.ssid[2][0] && + !lws_esp32.ssid[3][0]) + goto passthru; + + lwsl_notice("checking %d scan records\n", count_ap_records); + + for (n = 0; n < 4; n++) { + + if (!lws_esp32.ssid[(n + try_slot + 1) & 3][0]) + continue; + + lwsl_notice("looking for %s\n", lws_esp32.ssid[(n + try_slot + 1) & 3]); + + /* this ssid appears in scan results? */ + + for (m = 0; m < count_ap_records; m++) { + // lwsl_notice(" %s\n", ap_records[m].ssid); + if (strcmp((char *)ap_records[m].ssid, lws_esp32.ssid[(n + try_slot + 1) & 3]) == 0) + goto hit; + } + + continue; + +hit: + m = (n + try_slot + 1) & 3; + try_slot = m; + lwsl_notice("Attempting connection with slot %d: %s:\n", m, + lws_esp32.ssid[m]); + /* set the ssid we last tried to connect to */ + strncpy(lws_esp32.active_ssid, lws_esp32.ssid[m], + sizeof(lws_esp32.active_ssid) - 1); + lws_esp32.active_ssid[sizeof(lws_esp32.active_ssid) - 1] = '\0'; + + strncpy((char *)sta_config.sta.ssid, lws_esp32.ssid[m], sizeof(sta_config.sta.ssid) - 1); + strncpy((char *)sta_config.sta.password, lws_esp32.password[m], sizeof(sta_config.sta.password) - 1); + + tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, (const char *)&config.ap.ssid[7]); + lws_gapss_to(LWS_GAPSS_STAT); + + esp_wifi_set_config(WIFI_IF_STA, &sta_config); + esp_wifi_connect(); + + mdns_init(TCPIP_ADAPTER_IF_STA, &lws_esp32.mdns); + mdns_set_hostname(lws_esp32.mdns, (const char *)&config.ap.ssid[7]); + mdns_set_instance(lws_esp32.mdns, "instance"); + break; + } + + if (n == 4) + start_scan(); + +passthru: + if (lws_esp32.scan_consumer) + lws_esp32.scan_consumer(count_ap_records, ap_records, lws_esp32.scan_consumer_arg); + +} + esp_err_t lws_esp32_event_passthru(void *ctx, system_event_t *event) { + char slot[8]; + nvs_handle nvh; + uint32_t use; + switch(event->event_id) { case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; + //esp_wifi_connect(); +// break; + /* fallthru */ case SYSTEM_EVENT_STA_DISCONNECTED: + lwsl_notice("SYSTEM_EVENT_STA_DISCONNECTED\n"); lws_esp32.inet = 0; + lws_esp32.sta_ip[0] = '\0'; + lws_esp32.sta_mask[0] = '\0'; + lws_esp32.sta_gw[0] = '\0'; + lws_gapss_to(LWS_GAPSS_SCAN); + lws_esp32.inet = 0; + start_scan(); esp_wifi_connect(); break; case SYSTEM_EVENT_STA_GOT_IP: + lwsl_notice("SYSTEM_EVENT_STA_GOT_IP\n"); + lws_esp32.inet = 1; render_ip(lws_esp32.sta_ip, sizeof(lws_esp32.sta_ip) - 1, (uint8_t *)&event->event_info.got_ip.ip_info.ip); @@ -692,8 +871,23 @@ esp_err_t lws_esp32_event_passthru(void *ctx, system_event_t *event) (uint8_t *)&event->event_info.got_ip.ip_info.netmask); render_ip(lws_esp32.sta_gw, sizeof(lws_esp32.sta_gw) - 1, (uint8_t *)&event->event_info.got_ip.ip_info.gw); + + lwsl_notice(" --- Got IP %s\n", lws_esp32.sta_ip); + + if (!nvs_open("lws-station", NVS_READWRITE, &nvh)) { + lws_snprintf(slot, sizeof(slot) - 1, "%duse", try_slot); + use = 0; + nvs_get_u32(nvh, slot, &use); + nvs_set_u32(nvh, slot, use + 1); + nvs_commit(nvh); + nvs_close(nvh); + } + + lws_gapss_to(LWS_GAPSS_STAT_HAPPY); break; case SYSTEM_EVENT_SCAN_DONE: + lwsl_notice("SYSTEM_EVENT_SCAN_DONE\n"); + end_scan(); break; default: break; @@ -794,41 +988,38 @@ static const struct lws_plat_file_ops fops = { .LWS_FOP_SEEK_CUR = esp32_lws_fops_seek_cur, }; -static wifi_config_t config = { - .ap = { - .channel = 6, - .authmode = WIFI_AUTH_OPEN, - .max_connection = 1, - } }, sta_config = { - .sta = { - .bssid_set = 0, - } }; - int lws_esp32_wlan_nvs_get(int retry) { nvs_handle nvh; - char r[2], lws_esp32_force_ap = 0; + char r[2], lws_esp32_force_ap = 0, slot[12]; size_t s; uint8_t mac[6]; + int n, m; - esp_efuse_read_mac(mac); + esp_efuse_mac_get_default(mac); mac[5] |= 1; /* match the AP MAC */ snprintf(lws_esp32.serial, sizeof(lws_esp32.serial) - 1, "%02X%02X%02X", mac[3], mac[4], mac[5]); ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh)); - s = sizeof(config.sta.ssid) - 1; - if (nvs_get_str(nvh, "ssid0", (char *)sta_config.sta.ssid, &s) != ESP_OK) - lws_esp32_force_ap = 1; + config.sta.ssid[0] = '\0'; + config.sta.password[0] = '\0'; - /* set the ssid we last tried to connect to */ - strncpy(lws_esp32.active_ssid, (char *)sta_config.sta.ssid, sizeof(lws_esp32.active_ssid) - 1); - lws_esp32.active_ssid[sizeof(lws_esp32.active_ssid) - 1] = '\0'; + for (n = 0; n < 4; n++) { + lws_snprintf(slot, sizeof(slot) - 1, "%dssid", n); + s = sizeof(lws_esp32.ssid[0]) - 1; + lws_esp32.ssid[n][0] = '\0'; + m = nvs_get_str(nvh, slot, lws_esp32.ssid[n], &s); + lwsl_notice("%s: %s: %d\n", slot, lws_esp32.ssid[n], m); + + lws_snprintf(slot, sizeof(slot) - 1, "%dpassword", n); + s = sizeof(lws_esp32.password[0]) - 1; + lws_esp32.password[n][0] = '\0'; + m = nvs_get_str(nvh, slot, lws_esp32.password[n], &s); + lwsl_notice("%s: %s: %d\n", slot, lws_esp32.password[n], m); + } - s = sizeof(config.sta.password) - 1; - if (nvs_get_str(nvh, "password0", (char *)sta_config.sta.password, &s) != ESP_OK) - lws_esp32_force_ap = 1; s = sizeof(lws_esp32.serial) - 1; if (nvs_get_str(nvh, "serial", lws_esp32.serial, &s) != ESP_OK) lws_esp32_force_ap = 1; @@ -857,15 +1048,8 @@ lws_esp32_wlan_nvs_get(int retry) nvs_close(nvh); - if (retry && sta_config.sta.ssid[0]) { - tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, (const char *)&config.ap.ssid[7]); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config)); - ESP_ERROR_CHECK( esp_wifi_connect()); - - ESP_ERROR_CHECK(mdns_init(TCPIP_ADAPTER_IF_STA, &lws_esp32.mdns)); - mdns_set_hostname(lws_esp32.mdns, (const char *)&config.ap.ssid[7]); - mdns_set_instance(lws_esp32.mdns, "instance"); - } + lws_gapss_to(LWS_GAPSS_SCAN); + start_scan(); return lws_esp32_force_ap; } @@ -873,6 +1057,26 @@ lws_esp32_wlan_nvs_get(int retry) void lws_esp32_wlan_config(void) { + ledc_timer_config_t ledc_timer = { + .bit_num = LEDC_TIMER_13_BIT, + .freq_hz = 5000, + .speed_mode = LEDC_HIGH_SPEED_MODE, + .timer_num = LEDC_TIMER_0 + }; + + ledc_timer_config(&ledc_timer); + + /* user code needs to provide lws_esp32_leds_timer_cb */ + + leds_timer = xTimerCreate("lws_leds", pdMS_TO_TICKS(25), 1, NULL, + (TimerCallbackFunction_t)lws_esp32_leds_timer_cb); + scan_timer = xTimerCreate("lws_scan", pdMS_TO_TICKS(10000), 0, NULL, + (TimerCallbackFunction_t)lws_esp32_scan_timer_cb); + + scan_timer_exists = 1; + xTimerStart(leds_timer, 0); + + lws_esp32_wlan_nvs_get(0); tcpip_adapter_init(); } @@ -891,6 +1095,8 @@ lws_esp32_wlan_start_ap(void) ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config)); ESP_ERROR_CHECK( esp_wifi_start()); + esp_wifi_scan_start(&scan_config, false); + if (sta_config.sta.ssid[0]) { tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, (const char *)&config.ap.ssid[7]); esp_wifi_set_auto_connect(1); @@ -1011,11 +1217,12 @@ lws_esp32_set_creation_defaults(struct lws_context_creation_info *info) info->port = 443; info->fd_limit_per_thread = 30; - info->max_http_header_pool = 2; + info->max_http_header_pool = 3; info->max_http_header_data = 1024; info->pt_serv_buf_size = 4096; - info->keepalive_timeout = 5; - info->simultaneous_ssl_restriction = 2; + info->keepalive_timeout = 30; + info->timeout_secs = 30; + info->simultaneous_ssl_restriction = 3; info->options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; @@ -1068,20 +1275,6 @@ lws_esp32_init(struct lws_context_creation_info *info) char buf[512]; size_t s; int n; - ledc_timer_config_t ledc_timer = { - .bit_num = LEDC_TIMER_13_BIT, - .freq_hz = 5000, - .speed_mode = LEDC_HIGH_SPEED_MODE, - .timer_num = LEDC_TIMER_0 - }; - - ledc_timer_config(&ledc_timer); - - /* user code needs to provide lws_esp32_leds_timer_cb */ - - leds_timer = xTimerCreate("lws_leds", pdMS_TO_TICKS(25), 1, NULL, - (TimerCallbackFunction_t)lws_esp32_leds_timer_cb); - xTimerStart(leds_timer, 0); ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh)); n = 0; diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index e2cee958..1d86c584 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -1473,6 +1473,7 @@ struct lws { struct lws *pending_read_list_prev, *pending_read_list_next; #if defined(LWS_WITH_STATS) uint64_t accept_start_us; + char seen_rx; #endif #endif #ifdef LWS_WITH_HTTP_PROXY diff --git a/lib/ssl.c b/lib/ssl.c index ea1f4afc..d32e3a40 100644 --- a/lib/ssl.c +++ b/lib/ssl.c @@ -365,6 +365,15 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len) return LWS_SSL_CAPABLE_ERROR; } #endif +#if defined(LWS_WITH_STATS) + if (!wsi->seen_rx) { + lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_MS_SSL_RX_DELAY, + time_in_microseconds() - wsi->accept_start_us); + lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_SSL_CONNS_HAD_RX, 1); + wsi->seen_rx = 1; + } +#endif + lwsl_debug("%p: SSL_read says %d\n", wsi, n); /* manpage: returning 0 means connection shut down */ @@ -762,6 +771,7 @@ accepted: lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED, 1); #if defined(LWS_WITH_STATS) lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY, time_in_microseconds() - wsi->accept_start_us); + wsi->accept_start_us = time_in_microseconds(); #endif /* OK, we are accepted... give him some time to negotiate */ diff --git a/plugins/protocol_esp32_lws_scan.c b/plugins/protocol_esp32_lws_scan.c index 1a8c9f49..686599c2 100644 --- a/plugins/protocol_esp32_lws_scan.c +++ b/plugins/protocol_esp32_lws_scan.c @@ -85,14 +85,14 @@ struct per_vhost_data__esplws_scan { }; static const struct store_json store_json[] = { - { "\"ssid0\":\"", "ssid0" }, - { ",\"pw0\":\"", "password0" }, - { "\"ssid1\":\"", "ssid1" }, - { ",\"pw1\":\"", "password1" }, - { "\"ssid2\":\"", "ssid2" }, - { ",\"pw2\":\"", "password2" }, - { "\"ssid3\":\"", "ssid3" }, - { ",\"pw3\":\"", "password3" }, + { "\"ssid0\":\"", "0ssid" }, + { ",\"pw0\":\"", "0password" }, + { "\"ssid1\":\"", "1ssid" }, + { ",\"pw1\":\"", "1password" }, + { "\"ssid2\":\"", "2ssid" }, + { ",\"pw2\":\"", "2password" }, + { "\"ssid3\":\"", "3ssid" }, + { ",\"pw3\":\"", "3password" }, { ",\"access_pw\":\"", "access_pw" }, { "{\"group\":\"", "group" }, { "{\"role\":\"", "role" }, @@ -106,9 +106,6 @@ static wifi_scan_config_t scan_config = { .show_hidden = true }; -extern void (*lws_cb_scan_done)(void *); -extern void *lws_cb_scan_done_arg; - const esp_partition_t * ota_choose_part(void); @@ -130,7 +127,7 @@ enum enum_param_names { static void -scan_finished(void *v); +scan_finished(uint16_t count, wifi_ap_record_t *recs, void *v); static int esplws_simple_arg(char *dest, int len, const char *in, const char *match) @@ -161,8 +158,8 @@ scan_start(struct per_vhost_data__esplws_scan *vhd) return; vhd->scan_ongoing = 1; - lws_cb_scan_done = scan_finished; - lws_cb_scan_done_arg = vhd; + lws_esp32.scan_consumer = scan_finished; + lws_esp32.scan_consumer_arg = vhd; n = esp_wifi_scan_start(&scan_config, false); if (n != ESP_OK) lwsl_err("scan start failed %d\n", n); @@ -216,18 +213,21 @@ client_connection(struct per_vhost_data__esplws_scan *vhd, const char *file) } static void -scan_finished(void *v) +scan_finished(uint16_t count, wifi_ap_record_t *recs, void *v) { struct per_vhost_data__esplws_scan *vhd = v; struct per_session_data__esplws_scan *p = vhd->live_pss_list; + lwsl_notice("%s: count %d\n", __func__, count); + vhd->scan_ongoing = 0; - vhd->count_ap_records = ARRAY_SIZE(vhd->ap_records); - if (esp_wifi_scan_get_ap_records(&vhd->count_ap_records, vhd->ap_records) != ESP_OK) { - lwsl_err("%s: failed\n", __func__); - return; - } + if (count < ARRAY_SIZE(vhd->ap_records)) + vhd->count_ap_records = count; + else + vhd->count_ap_records = ARRAY_SIZE(vhd->ap_records); + + memcpy(vhd->ap_records, recs, vhd->count_ap_records * sizeof(*recs)); while (p) { if (p->scan_state != SCAN_STATE_INITIAL && p->scan_state != SCAN_STATE_NONE) @@ -333,7 +333,6 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason, vhd->vhost = lws_get_vhost(wsi); vhd->timer = xTimerCreate("x", pdMS_TO_TICKS(10000), 1, vhd, (TimerCallbackFunction_t)timer_cb); - xTimerStart(vhd->timer, 0); vhd->scan_ongoing = 0; strcpy(vhd->json, " { }"); scan_start(vhd); @@ -347,6 +346,11 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason, break; case LWS_CALLBACK_ESTABLISHED: + lwsl_notice("%s: ESTABLISHED\n", __func__); + if (!vhd->live_pss_list) { + scan_start(vhd); + xTimerStart(vhd->timer, 0); + } vhd->count_live_pss++; pss->next = vhd->live_pss_list; vhd->live_pss_list = pss; @@ -374,7 +378,7 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason, struct timeval t; uint8_t mac[6]; struct lws_esp32_image i; - char img_factory[512], img_ota[512], group[16]; + char img_factory[512], img_ota[512], group[16], role[16]; int grt; case SCAN_STATE_INITIAL: @@ -385,7 +389,10 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason, pss->last_send = t; - ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh)); + if (nvs_open("lws-station", NVS_READWRITE, &nvh)) { + lwsl_err("unable to open nvs\n"); + return -1; + } n = 0; if (nvs_get_blob(nvh, "ssl-pub.pem", NULL, &s) == ESP_OK) n = 1; @@ -393,7 +400,9 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason, n |= 2; s = sizeof(group) - 1; group[0] = '\0'; + role[0] = '\0'; nvs_get_str(nvh, "group", group, &s); + nvs_get_str(nvh, "role", role, &s); nvs_close(nvh); @@ -405,7 +414,7 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason, grt = lws_esp32_get_reboot_type(); - esp_efuse_read_mac(mac); + esp_efuse_mac_get_default(mac); strcpy(img_factory, " { \"date\": \"Empty\" }"); strcpy(img_ota, " { \"date\": \"Empty\" }"); @@ -431,6 +440,7 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason, " \"conn_mask\":\"%s\",\n" " \"conn_gw\":\"%s\",\n" " \"group\":\"%s\",\n" + " \"role\":\"%s\",\n" " \"img_factory\": %s,\n" " \"img_ota\": %s,\n", lws_esp32.model, @@ -445,7 +455,7 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason, lws_esp32.sta_ip, lws_esp32.sta_mask, lws_esp32.sta_gw, - group, + group, role, img_factory, img_ota ); @@ -486,13 +496,13 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason, s = sizeof(ssid) - 1; ssid[0] = '\0'; - lws_snprintf(name, sizeof(name) - 1, "ssid%d", m); + lws_snprintf(name, sizeof(name) - 1, "%dssid", m); nvs_get_str(nvh, name, ssid, &s); - lws_snprintf(name, sizeof(name) - 1, "password%d", m); + lws_snprintf(name, sizeof(name) - 1, "%dpassword", m); s = 10; nvs_get_str(nvh, name, NULL, &s); pp = !!s; - lws_snprintf(name, sizeof(name) - 1, "use%d", m); + lws_snprintf(name, sizeof(name) - 1, "%duse", m); nvs_get_u32(nvh, name, &use); p += snprintf((char *)p, end - p, @@ -568,8 +578,8 @@ issue: { const char *sect = "\"app\": {", *b; nvs_handle nvh; - char p[64]; - int n; + char p[64], use[6]; + int n, si = -1; if (strstr((const char *)in, "identify")) { lws_esp32_identify_physical_device(); @@ -591,6 +601,11 @@ issue: break; } + if (!esplws_simple_arg(p, sizeof(p), in, ",\"slot\":\"")) + si = atoi(p); + + lwsl_notice("si %d\n", si); + for (n = 0; n < ARRAY_SIZE(store_json); n++) { if (esplws_simple_arg(p, sizeof(p), in, store_json[n].j)) continue; @@ -599,7 +614,7 @@ issue: if (n == 8 && lws_esp32_get_reboot_type() != LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON) continue; - lwsl_notice("%s '%s\n", store_json[n].nvs, p); + //lwsl_notice("%s: %s '%s'\n", __func__, store_json[n].nvs, p); if (n == 9) { strncpy(lws_esp32.group, p, sizeof(lws_esp32.group) - 1); lws_esp32.group[sizeof(lws_esp32.group) - 1] = '\0'; @@ -609,10 +624,29 @@ issue: lws_esp32.role[sizeof(lws_esp32.role) - 1] = '\0'; } - if (nvs_set_str(nvh, store_json[n].nvs, p) != ESP_OK) { + if (lws_nvs_set_str(nvh, store_json[n].nvs, p) != ESP_OK) { lwsl_err("Unable to store %s in nvm\n", store_json[n].nvs); goto bail_nvs; } + + if (si != -1 && n < 8) { + if (!(n & 1)) { + strncpy(lws_esp32.ssid[(n >> 1) & 3], p, + sizeof(lws_esp32.ssid[0])); + lws_esp32.ssid[(n >> 1) & 3] + [sizeof(lws_esp32.ssid[0]) - 1] = '\0'; + lws_snprintf(use, sizeof(use) - 1, "%duse", si); + lwsl_notice("resetting %s to 0\n", use); + nvs_set_u32(nvh, use, 0); + + } else { + strncpy(lws_esp32.password[(n >> 1) & 3], p, + sizeof(lws_esp32.password[0])); + lws_esp32.password[(n >> 1) & 3] + [sizeof(lws_esp32.password[0]) - 1] = '\0'; + } + } + } nvs_commit(nvh); @@ -702,6 +736,8 @@ auton: vhd->count_live_pss--; } + if (!vhd->live_pss_list) + xTimerStop(vhd->timer, 0); break; /* "factory" POST handling */ @@ -738,7 +774,7 @@ auton: if (lws_esp32_get_reboot_type() == LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON) { if (lws_spa_get_string(pss->spa, EPN_SERIAL)) { - if (nvs_set_str(nvh, "serial", lws_spa_get_string(pss->spa, EPN_SERIAL)) != ESP_OK) { + if (lws_nvs_set_str(nvh, "serial", lws_spa_get_string(pss->spa, EPN_SERIAL)) != ESP_OK) { lwsl_err("Unable to store serial in nvm\n"); goto bail_nvs; } @@ -747,7 +783,7 @@ auton: } if (lws_spa_get_string(pss->spa, EPN_OPTS)) { - if (nvs_set_str(nvh, "opts", lws_spa_get_string(pss->spa, EPN_OPTS)) != ESP_OK) { + if (lws_nvs_set_str(nvh, "opts", lws_spa_get_string(pss->spa, EPN_OPTS)) != ESP_OK) { lwsl_err("Unable to store options in nvm\n"); goto bail_nvs; }