tonyp7 / esp32-wifi-manager

Captive Portal for ESP32 that can connect to a saved wireless network or start an access point where you can connect to existing wifis.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

httpd: httpd_server_init: error in listen (112)

baldhead69 opened this issue · comments

Hi,

I am trying to do my "websocket server" work with "esp32-wifi-manager" and i get the error:

httpd: httpd_server_init: error in listen (112)
in
httpd_start(&server, &config);

I think because the "esp32-wifi-manager" already started "httpd server".

I would like to know if i can turn off the "esp32-wifi-manager" or some other way that i can resolve this without using "http_app_set_handler_hook (HTTP_GET, & my_get_handler);"

I need that this variable be global because i use it in many functions inside my server:
static httpd_handle_t server = NULL;

Thank's.

static httpd_handle_t server = NULL; 

void init_webSocket_server()  
{   
    wifi_manager_start(); 

    wifi_manager_set_callback(WM_EVENT_STA_GOT_IP, &cb_connect_handler);

    wifi_manager_set_callback(WM_EVENT_STA_DISCONNECTED, &cb_disconnect_handler);
}


static void cb_connect_handler(void *pvParameter)
{	
    ESP_LOGI(TAG, "I have a connection!");

    if ( server == NULL )
    {
        start_webSocket_server();
    }
}


static void cb_disconnect_handler(void *pvParameter)
{
    ESP_LOGI(TAG, "I have a DIS connection!");

    if ( server != NULL )
    {
        stop_webSocket_server();
        server = NULL;
    }
}


static void start_webSocket_server()
{    
    httpd_config_t config = HTTPD_DEFAULT_CONFIG(); 
     
    ESP_LOGI(TAG, "Starting WebSocket Server");

    esp_err_t ret;
    ret = httpd_start(&server, &config);    // httpd: httpd_server_init: error in listen (112)

    if ( ret != ESP_OK )
    {
        ESP_LOGE(TAG, "Failed to start the server!");

        printf("\nhttpd_start: %d\n", ret);

        return;
    }
    
    // URI handler for websocket client(s) message reception.
    static const httpd_uri_t get_clients_message =
    {
        .uri       = "/",  
        .method    = HTTP_GET,
        .handler   = get_clients_message_handler,
        .user_ctx  = NULL,
        .is_websocket = true
    };
    httpd_register_uri_handler(server, &get_clients_message);
}


static void stop_webSocket_server()
{
    /* Stop the httpd server */
    httpd_stop(server);   
}

Hi,

You could include "http_app.h" in your code and call http_app_stop(); but that would not solve your issue entirely because there are events which will automatically restart the server (such as a wifi loss / attempt to reconnect)

There are a few options I can see:

  • add a menu config param to toggle this is_websocket conf. You could then hook into wifi_manager.
  • Run your server on different port ( add .server_port = 8080 in your config for instance)
  • Add an API to register uri_handler instead of a hook

The problem though, is that esp32_wifi_manager needs to have a global URI handler ( .uri = "*" ). That's the only way you can kick off the captive portal since your device will try to acess random pages.

I'm open to suggestions!

Hi,

Sorry, i am lost :(, but thank's for the reply.

@baldhead69 were you able to solve it ?

@baldhead69 were you able to solve it ?

No. For now i am working in other things. In the future i need to encounter a simple way to input wifi ssid and wifi password.

Hi,

You could include "http_app.h" in your code and call http_app_stop(); but that would not solve your issue entirely because there are events which will automatically restart the server (such as a wifi loss / attempt to reconnect)

There are a few options I can see:

  • add a menu config param to toggle this is_websocket conf. You could then hook into wifi_manager.
  • Run your server on different port ( add .server_port = 8080 in your config for instance)
  • Add an API to register uri_handler instead of a hook

The problem though, is that esp32_wifi_manager needs to have a global URI handler ( .uri = "*" ). That's the only way you can kick off the captive portal since your device will try to acess random pages.

I'm open to suggestions!

@tonyp7 What do you mean by the last point(Add an API to register uri_handler instead of a hook)? httpd_register_uri_handler is not the right way to go ahead?

Hi,

You could include "http_app.h" in your code and call http_app_stop(); but that would not solve your issue entirely because there are events which will automatically restart the server (such as a wifi loss / attempt to reconnect)

There are a few options I can see:

  • add a menu config param to toggle this is_websocket conf. You could then hook into wifi_manager.
  • Run your server on different port ( add .server_port = 8080 in your config for instance)
  • Add an API to register uri_handler instead of a hook

The problem though, is that esp32_wifi_manager needs to have a global URI handler ( .uri = "*" ). That's the only way you can kick off the captive portal since your device will try to acess random pages.

I'm open to suggestions!

Hello I was stuck on this too.

// Libraries
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <esp_wifi.h>
#include <esp_netif.h>
#include <http_app.h>
#include <freertos/FreeRTOS.h>
#include <esp_http_server.h>
#include <freertos/task.h>
#include <esp_ota_ops.h>
#include <esp_system.h>
#include <lwip/ip4_addr.h>
#include <esp_log.h>
#include <nvs_flash.h>
#include <sys/param.h>

#include <wifi_manager.h>

#define WIFI_SSID "ESP32 OTA Update"

// Tag used for ESP Serial Console Messages
static const char TAG[] = "main";

void monitoring_task(void *pvParameter) {
for (;;) {
ESP_LOGI(TAG, "free heap: %"PRIu32, esp_get_free_heap_size());
vTaskDelay(pdMS_TO_TICKS(10000));
}
}

/*

  • Serve OTA update portal (index.html)
    */
    extern const uint8_t index_html_start[] asm("_binary_index_html_start");
    extern const uint8_t index_html_end[] asm("_binary_index_html_end");

esp_err_t index_get_handler(httpd_req_t *req)
{
httpd_resp_send(req, (const char *) index_html_start, index_html_end - index_html_start);
return ESP_OK;
}

esp_err_t update_post_handler(httpd_req_t *req)
{
char buf[2000];
esp_ota_handle_t ota_handle;
int remaining = req->content_len;

const esp_partition_t *ota_partition = esp_ota_get_next_update_partition(NULL);
ESP_ERROR_CHECK(esp_ota_begin(ota_partition, OTA_SIZE_UNKNOWN, &ota_handle));

while (remaining > 0) {
	int recv_len = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf)));

	// Timeout Error: Just retry
	if (recv_len == HTTPD_SOCK_ERR_TIMEOUT) {
		continue;

	// Serious Error: Abort OTA
	} else if (recv_len <= 0) {
		httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Protocol Error");
		return ESP_FAIL;
	}

	// Successful Upload: Flash firmware chunk
	if (esp_ota_write(ota_handle, (const void *)buf, recv_len) != ESP_OK) {
		httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Flash Error");
		return ESP_FAIL;
	}

	remaining -= recv_len;
}

// Validate and switch to new OTA image and reboot
if (esp_ota_end(ota_handle) != ESP_OK || esp_ota_set_boot_partition(ota_partition) != ESP_OK) {
		httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Validation / Activation Error");
		return ESP_FAIL;
}

httpd_resp_sendstr(req, "Firmware update complete, rebooting now!\n");

vTaskDelay(500 / portTICK_PERIOD_MS);
esp_restart();

return ESP_OK;

}

/*

  • HTTP Server
    */
    httpd_uri_t index_get = {
    .uri = "/",
    .method = HTTP_GET,
    .handler = index_get_handler,
    .user_ctx = NULL
    };

httpd_uri_t update_post = {
.uri = "/update",
.method = HTTP_POST,
.handler = update_post_handler,
.user_ctx = NULL
};

static esp_err_t http_server_init(void)
{
static httpd_handle_t http_server = NULL;

httpd_config_t config = HTTPD_DEFAULT_CONFIG();

if (httpd_start(&http_server, &config) == ESP_OK) {
	httpd_register_uri_handler(http_server, &index_get);
	httpd_register_uri_handler(http_server, &update_post);
}

return http_server == NULL ? ESP_FAIL : ESP_OK;

}

void ota_update_task(void *pvParameters) {
// Mark current app as valid
const esp_partition_t *partition = esp_ota_get_running_partition();
ESP_LOGI(TAG, "Currently running partition:%s\r\n", partition->label);

esp_ota_img_states_t ota_state;
if (esp_ota_get_state_partition(partition, &ota_state) == ESP_OK) {
    if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
        esp_ota_mark_app_valid_cancel_rollback();
    }
}
for (;;) {
    ESP_LOGI(TAG, "OTA Running");
    vTaskDelay(pdMS_TO_TICKS(10000));
}

}

void ota_update_task_create(void) {

http_server_init();

// Create the OTA updates task
xTaskCreatePinnedToCore(&ota_update_task, "ota task", 4056, NULL, 1, NULL, 1);

}

void cb_connection_ok(void *pvParameter) {

ip_event_got_ip_t *param = (ip_event_got_ip_t *)pvParameter;

//Transform IP to human readable string
char str_ip[16];
esp_ip4addr_ntoa(&param->ip_info.ip, str_ip, IP4ADDR_STRLEN_MAX);

esp_ip4_addr_t zero_ip;
memset(&zero_ip, 0, sizeof(esp_ip4_addr_t));

if (memcmp(&param->ip_info.ip, &zero_ip, sizeof(esp_ip4_addr_t)) != 0) {
	ota_update_task_create();
}

}

void app_main(void) {
esp_err_t ret = nvs_flash_init();

if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
    ESP_ERROR_CHECK(nvs_flash_erase());
    ret = nvs_flash_init();
}

ESP_ERROR_CHECK(ret);

// Start the Wifi Manager
wifi_manager_start();

// Register a callback to integrate code with the wifi manager
wifi_manager_set_callback(WM_EVENT_STA_GOT_IP, &cb_connection_ok);

// Here, create a task on core 1 that monitors free heap memory
xTaskCreatePinnedToCore(&monitoring_task, "monitoring task", 4056, NULL, 1, NULL, 1);

}
I was trying to have OTA while having wifi manager, but the problem occur when i upload bin file it become http 404 error. I think wifi manager still running on the background. it disturb the OTA.

I am not using wifi manager.

I'm doing other things, I'll leave this ssid and password configuration for the end.