Copyright © https://mongoose-os.com

Mongoose OS Forum

frame

Switch index.html

pjapja Cambridge

Hi,

I'm in the process of building a web server interface (in C) to setup the WiFi interface (using ESP32 HW) based on the https://github.com/mongoose-os-apps/wifi-setup-web example code. When the user has completed configuration the WiFi the unit reboots and connects (as a WiFi terminal) to the new WiFi network.

After connection to the WiFi network I wish to switch the index.html file to present a different web interface (allow user to interact with the device). I can use the C function mgos_vfs_rename to switch the index.html file but this is rather a clunky way of achieving this. I looked at using mgos_http_server_set_document_root but as the file system is flat (no folders I believe) this is of little use.

Does anyone have suggestions as to the best way to switch the web/http interface to a different index.html file ?

Thanks

Paul

Comments

  • pjapja Cambridge

    In order to serve different html files when the root (/ or index.html) is requested from the web server I tried adding a event handler

    mgos_register_http_endpoint("/", root_handler, NULL);

    With a handler as detailed below

    `

    The event handler code is

    static void root_handler(struct mg_connection *mg_con, int ev, void *p, void *user_data) {

      if (ev == MG_EV_HTTP_REQUEST) {
    
        fprintf(stdout, "%s: PJA: 2 mg_con   =%p\n", __FUNCTION__, mg_con);
        fprintf(stdout, "%s: PJA: 3 user_data=%p\n", __FUNCTION__, user_data);
    
        if( user_data == NULL ) {
            if( setup_mode ) {
                mg_http_serve_file(mg_con, (struct http_message *) "", "setup.html", mg_mk_str("text/html"), mg_mk_str(""));
            }
            else {
                mg_http_serve_file(mg_con, (struct http_message *) "", "product.html", mg_mk_str("text/html"), mg_mk_str(""));
            }
            LOG(LL_INFO, ("PJA: 4"));
        }
        else {
            mg_serve_http(mg_con, (struct http_message *) user_data, s_http_server_opts);
            LOG(LL_INFO, ("PJA: 5"));
        }
    
      }
    

    }
    `

    This serves setup.html or product.html depending upon the state of the setup_mode flag, except it does not call mg_serve_http because user_data is always NULL. Therefore none of the other files (*.css or *.js) are served.

    I expected user_data not to be NULL when a particular file was requested by the client.

    Any pointers greatly appreciated

    Paul

  • pjapja Cambridge
    edited March 18

    I solved the problem described as follows (not sure why the code quote does not show this all as code)

    mgos_register_http_endpoint("/", root_handler, NULL);

    `
    /**
    * @brief Convert from mg_str struct to C string (null terminated).
    * The caller must free the memory allocated to hold the C string.
    */
    static char * mg_str2c_str(struct mg_str *mgstr)
    {
    char * textBuf;

    if( mgstr->len > 0 ) {
        textBuf = malloc(mgstr->len + 1);
        strncpy(textBuf, mgstr->p, mgstr->len);
        textBuf[mgstr->len] = '\0';
        return textBuf;
    }
    return "";
    

    }
    `
    /**
    * @brief handle all http requests and filter out the root and index.html requests.
    * If a / or /index.html is made then
    */
    static void root_handler(struct mg_connection *mg_con, int ev, void *p, void *user_data) {
    static struct mg_serve_http_opts s_http_server_opts;

    if (ev == MG_EV_HTTP_REQUEST) {
        int root_request = 0;
        struct http_message *hm = (struct http_message *) p;
        char *uri = NULL;
    
        if (hm->uri.len > 0) {
            uri = mg_str2c_str(&hm->uri);
            if (strcmp(uri, "/") == 0 || strcmp(uri, "/index.html") == 0) {
                root_request = 1;
            }
            free(uri);
            uri = NULL;
        }
    
        if (root_request) {
    
            if ( setup_mode_flag ) {
    
                mg_http_serve_file(mg_con, (struct http_message *) p, SETUP_HTML, mg_mk_str("text/html"), mg_mk_str(""));
    
            } else {
    
                mg_http_serve_file(mg_con, (struct http_message *) p, PRODUCT_HTML, mg_mk_str("text/html"), mg_mk_str(""));
    
            }
    
        } else {
    
            //As it's not a root request serve the file requested.
            if (hm != NULL) {
                mg_serve_http(mg_con, hm, s_http_server_opts);
            }
    
        }
    
    }
    

    }

  • mamuespmamuesp Germany/Northern coast
    edited May 1

    Well, I'm a little late with a suggestion, but I solved this problem in one of my projects with some JavaScript and CSS. In the first step, the web page displays only the WiFi settings. If I am connected and called via an IP address collected by the WiFi DHCP server, I show the rest - including the WiFi settings, since they can of course be changed from the current WiFi area.

    I put the "non AP mode" part into a <div> wrapper, which is hidden by default (e.g. class 'hidden' with corresponding settings). The JavaScript gets the current status information (e.g. via an XHTTP request to '/rpc/Sys.GetInfo' and checks the settings. You can also write the corresponding info in the configuration (example: "myCon.WiFi.isSet" -> "true" or "false") and then read here in the browser, this is also a good solution.

    If it is clear that the WiFi is set, you can remove the'hidden' class and everything is fine. This solution is very flexible and easy to adapt. Just my 2 cents .... ;-)

Sign In or Register to comment.