Tiny WebServer crashes after some hours



  • Hi folks

    I have the problem, that the following code (it's a tiny web server) crashes after some hours.
    I don't know what the problem exactly is, but it is not reachable after some hours of perfect running.
    The label "labelWebServer" does show "RUNS", but I get a "ERR_CONNECTION_TIMED_OUT" because the server does not response anymore until I restart the device.

    You can call the tiny web server like:
    http://{IpAddress}/api/v1.0/level

    Does anyone have a idea, what I am doing wrong?

    Annotation: It is one of 2 threads. My second thread reads out some sensors and calculates the "level". The second thread is working like a charm.

    Code Example: Tiny Web Server

    from m5stack import *`
    from m5ui import *
    from uiflow import *
    import random
    import unit
    import wifiCfg
    import socket
    import _thread as th
    
    setScreenColor(0x000000)
    
    labelWebServer = M5TextBox(240, 20, "WS", lcd.FONT_Default,0xFFFFFF, rotate=0)
    labelIpAddress = M5TextBox(300, 170, "xxx.xxx.xxx.xxx", lcd.FONT_Default,0xFFFFFF, rotate=270)
    levelPercent = 100
    
    wifiCfg.screenShow()
    wifiCfg.autoConnect(lcdShow = True)
    
    def webServer():
    
      global levelPercent
    
      ip = wifiCfg.wlan_sta.ifconfig()
      server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
      server.bind((ip[0], 80))
      server.listen(1)
    
      web_response_json = """{"data":{"deviceName":"BlablaLevel","deviceId": "BlablablaWhatever","value": @value@,"unit": "@unit@"}}"""
    
      web_error_404 = """<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL was not found on this server.</p></body></html>"""
    
      response = None
    
      while True:
    
        try:
    
          labelIpAddress.setText('')
          labelIpAddress.setText('IP ' + wifiCfg.wlan_sta.ifconfig()[0])
    
          if not wifiCfg.wlan_sta.isconnected():
            labelWebServer.setText('WS: RECON')
            wifiCfg.reconnect()
    
          labelWebServer.setText('WS: RUNS')
          
          conn, addr = server.accept()
          request = conn.recv(1024)
          request = str(request)
    
          isRequestLevel = request.find('/api/v1.0/level ') >= 0
      
          if isRequestLevel :
            labelWebServer.setText('WS: 200')
            json = web_response_json
            json = json.replace('@value@', str(("%.2f"%(levelPercent))))
            json = json.replace('@unit@', '%')
            response = json
            conn.send('HTTP/1.1 200 OK\r\n')
            conn.send('Content-Type: application/json\r\n')
            conn.send('Connection: close\r\n\r\n')
          else :
            labelWebServer.setText('WS: 404')
            response = web_error_404
            conn.send('HTTP/1.1 404 NOT FOUND\r\n')
            conn.send('Content-Type: text/html\r\n')
            conn.send('Connection: close\r\n\r\n')
    
          conn.sendall(response)
        
        except Exception as e:
          labelWebServer.setText('WS: ERR')
    
        finally:
          try:
            conn.close()
          except Exception as e:
            labelWebServer.setText('WS: ERR')
    
    
    th.start_new_thread(webServer, ())
    


  • I am experimenting with this code. Maybe it helps....

    server.settimeout(30)

    # ========================================
    # WEB SERVER
    # ========================================
    def webServer():
    
        global levelPercent, setupMode
    
        web_response_json = """{"data":{"deviceName":"blablabla","deviceId": "blablabla","value": @value@,"unit": "@unit@"}}"""
    
        web_error_404 = """<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL was not found on this server.</p></body></html>"""
    
        while True:
    
            try:
    
                labelIpAddress.setText('')
    
                if not wifiCfg.wlan_sta.isconnected():
                    labelWebServer.setText('WS: RECON')
                    wifiCfg.reconnect()
                else:
                    ip = wifiCfg.wlan_sta.ifconfig()
                    labelIpAddress.setText('IP ' + wifiCfg.wlan_sta.ifconfig()[0])
                    
                    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                    server.settimeout(30)
                    server.bind((ip[0], 80))
                    server.listen(1)
                
                    labelWebServer.setText('WS: RUNS')
    
                    (conn, addr) = server.accept()
                    request = conn.recv(1024)
                    
                    if request:
                      request = str(request)
      
                      isRequestLevel = request.find('/api/v1.0/level ') >= 0
      
                      if isRequestLevel:
                          labelWebServer.setText('WS: 200')
                          json = web_response_json
                          json = json.replace('@value@', str('%.2f'
                                  % levelPercent))
                          json = json.replace('@unit@', '%')
                          response = json
                          conn.send('HTTP/1.1 200 OK\r\n')
                          conn.send('Content-Type: application/json\r\n')
                          conn.send('Connection: close\r\n\r\n')
                      else:
                          labelWebServer.setText('WS: 404')
                          response = web_error_404
                          conn.send('HTTP/1.1 404 NOT FOUND\r\n')
                          conn.send('Content-Type: text/html\r\n')
                          conn.send('Connection: close\r\n\r\n')
      
                      conn.sendall(response)
    
            except Exception as e:
                gc.collect()
                labelWebServer.setText('WS: ERR')
    
            finally:
                try:
                    conn.close()
                    server.close()
                except Exception as e:
                    pass
                finally:
                    pass
    

  • M5Stack

    I also had the same issue, or that it would crash after pressing a html button too many times. I never found the reason why



  • @lukasmaximus said in Tiny WebServer crashes after some hours:

    I also had the same issue, or that it would crash after pressing a html button too many times. I never found the reason why

    In my opinion the problem is my code line request = conn.recv(1024)

    If the connection fails, the program never will com back here to life. So my code fragment to reconnect will never run.
    It would help if request = conn.recv(1024) would crash in case of lost connection, so that I can apply code to setup everything new.



  • @lukasmaximus said in Tiny WebServer crashes after some hours:

    I also had the same issue, or that it would crash after pressing a html button too many times. I never found the reason why

    Hi Lukas

    Look at my solution. It runs since 2 days without a problem. If the socket crashes it will setup again after 30 seconds.
    Maybe you can adopt it

    # ========================================
    # WEB SERVER
    # ========================================
    def webServer():
    
        global levelPercent, setupMode
    
        web_response_json = """{"data":{"deviceName":"blablabla","deviceId": "blablabla","value": @value@,"unit": "@unit@"}}"""
    
        web_error_404 = """<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL was not found on this server.</p></body></html>"""
    
        while True:
    
            try:
    
                labelIpAddress.setText('')
    
                if not wifiCfg.wlan_sta.isconnected():
                    labelWebServer.setText('WS: RECON')
                    wifiCfg.reconnect()
                else:
                    ip = wifiCfg.wlan_sta.ifconfig()
                    labelIpAddress.setText('IP ' + wifiCfg.wlan_sta.ifconfig()[0])
                    
                    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                    server.settimeout(30)
                    server.bind((ip[0], 80))
                    server.listen(1)
                
                    labelWebServer.setText('WS: RUNS')
    
                    (conn, addr) = server.accept()
                    request = conn.recv(1024)
                    
                    if request:
                      request = str(request)
      
                      isRequestLevel = request.find('/api/v1.0/level ') >= 0
      
                      if isRequestLevel:
                          labelWebServer.setText('WS: 200')
                          json = web_response_json
                          json = json.replace('@value@', str('%.2f'
                                  % levelPercent))
                          json = json.replace('@unit@', '%')
                          response = json
                          conn.send('HTTP/1.1 200 OK\r\n')
                          conn.send('Content-Type: application/json\r\n')
                          conn.send('Connection: close\r\n\r\n')
                      else:
                          labelWebServer.setText('WS: 404')
                          response = web_error_404
                          conn.send('HTTP/1.1 404 NOT FOUND\r\n')
                          conn.send('Content-Type: text/html\r\n')
                          conn.send('Connection: close\r\n\r\n')
      
                      conn.sendall(response)
    
            except Exception as e:
                gc.collect()
                labelWebServer.setText('WS: ERR')
    
            finally:
                try:
                    conn.close()
                    server.close()
                except Exception as e:
                    pass
                finally:
                    pass
    

  • M5Stack

    great job