jczic / MicroWebSrv

A micro HTTP Web server that supports WebSockets, html/python language templating and routing handlers, for MicroPython (used on Pycom modules & ESP32)
https://github.com/jczic/MicroWebSrv
MIT License
640 stars 115 forks source link

httpResponse doesn't send the response after reconnecting wifi #64

Closed dukeduck1984 closed 4 years ago

dukeduck1984 commented 4 years ago

Hi,

I have an API which is used to connet/reconnet to a Wifi AP, I wanted this API to WriteResponseOK after the connection is established, however it does send back any response even though the connection was made. For other APIs in my code, httpResponse worked flawlessly, so I think it may be related to wlan methods.

This is the API.

        @MicroWebSrv.route('/wifi', 'POST')
        def wifi_post(httpClient, httpResponse):
            wifi_dict = httpClient.ReadRequestContentAsJSON()
            new_ip = wifi.sta_connect(wifi_dict['ssid'], wifi_dict['pass'])
            if wifi.is_connected():
                if not rtc.is_synced():
                    print('Syncing RTC...')
                    rtc.sync()
                print(new_ip)
                httpResponse.WriteResponseOk()
            else:
                httpResponse.WriteResponseInternalServerError()

So the above API gets a post request with below json data:

{
  "ssid": "new-wifi-ap",
  "pass": "12345678"
}

Below is the wifi.sta_connect() method:

    def sta_connect(self, ap_ssid, ap_pass, verify_ap=False):
        """
        Connect to an Access Point by its SSID and Password
        return: string; the IP of the STA
        """
        # Attempt connection only if SSID can be found
        if verify_ap:
            if not self.verify_ap(ap_ssid):
                print('Network "' + ap_ssid + '" does not present')
                return None

        # Disconnect current wifi network
        if self.sta.isconnected():
            print('Disconnecting from current network...')
            self.sta.disconnect()
            utime.sleep(1)
            self.sta.active(False)
            utime.sleep_ms(200)
            self.sta.active(True)
            utime.sleep_ms(200)
        start = utime.ticks_ms()
        timeout = 10000
        while not self.sta.isconnected():
            if utime.ticks_diff(utime.ticks_ms(), start) > timeout:
                print('Connecting to "' + ap_ssid + '" Timeout')
                if self.ssid and self.pwd:
                    print('Restore the connection with "' + self.ssid + '"')
                    try:
                        self.sta_connect(self.ssid, self.pwd)
                    except:
                        pass
                else:
                    return None
                break
            print('Connecting to "' + ap_ssid + '"...')
            self.sta.connect(ap_ssid, ap_pass)
            while not self.sta.isconnected() and utime.ticks_diff(utime.ticks_ms(), start) < timeout:
                print('Connecting...')
                utime.sleep_ms(1500)
        else:
            print('Network "' + ap_ssid + '" Connected!')
            # if successfully connected, store the SSID & Password
            self.ssid = ap_ssid
            self.pwd = ap_pass
            return self.get_sta_ip_addr()

In the REPL I can see the connection was successfully made, then it just got stuck right at where httpResponse.WriteResponseOk() is, in the browser console, that request was in pending status until timeout.

What can be the issue?

Firmware: MicroPython v1.11-240-g519746cae on 2019-08-26; ESP32 module (spiram) with ESP32

Thanks. Kaiyuan

dukeduck1984 commented 4 years ago

Ok, I think I figured out why - when I connected directly to the ESP32's own AP (visiting via 192.168.4.1), the above code worked. It won't work if the ESP32 connects to my home wifi and I visit the ESP32 through home wifi.

But is there a workaround?

jczic commented 4 years ago

Hi @dukeduck1984, A httpResponse is sent trought the current TCP/IP(HTTP) persistent connection. If the main WLAN interface changes, the connection is broken. It's normal. Could you try my WLAN lib to play with the two interfaces : https://github.com/jczic/MicroWifi (no help but some simple functions). You can scan APs, connect to an AP, during a connection from a station 👍

dukeduck1984 commented 4 years ago

Thanks @jczic , I will give MicroWifi a try.