1515from request import Request
1616import gc
1717import os
18+ import machine
1819
1920
2021class GurgleAppsWebserver :
@@ -34,6 +35,7 @@ def __init__(self, wifi_ssid, wifi_password, port=80, timeout=20, doc_root="/www
3435 self .log_level = log_level
3536 self .wlan_sta = network .WLAN (network .STA_IF )
3637 self .wlan_ap = network .WLAN (network .AP_IF )
38+ self .enable_cors = False
3739 self .html = """<!DOCTYPE html>
3840 <html>
3941 <head> <title>GurgleApps.com Webserver</title> </head>
@@ -50,50 +52,88 @@ def __init__(self, wifi_ssid, wifi_password, port=80, timeout=20, doc_root="/www
5052 self .server_running = False
5153
5254
53- def connect_wifi (self , ssid , password ):
54- self .wifi_ssid = ssid
55- self .wifi_password = password
56- # Deactivate AP mode
57- self .wlan_ap .active (False )
58- if self .wlan_sta .isconnected ():
59- print ("Already connected to Wi-Fi. IP: " + self .wlan_sta .ifconfig ()[0 ])
60- self .wlan_sta .disconnect ()
61- self .wlan_sta .active (False )
62- time .sleep (1 )
63- print ("Disconnected from Wi-Fi." )
64-
65- # Activate Wi-Fi mode and connect
66- self .wlan_sta .active (True )
67- self .wlan_sta .connect (ssid , password )
68- # Wait for connection
69- print ("Connecting to Wi-Fi..." )
70- for _ in range (self .timeout ):
71- time .sleep (1 )
55+ async def connect_wifi (self , ssid , password ):
56+ try :
57+ self .wifi_ssid = ssid
58+ self .wifi_password = password
59+ # Deactivate AP mode
60+ #self.wlan_ap.active(False)
7261 if self .wlan_sta .isconnected ():
73- self .ip_address = self .wlan_sta .ifconfig ()[0 ]
74- print (f"Connected to Wi-Fi. IP: { self .ip_address } " )
75- return True
76- print ("Failed to connect to Wi-Fi." )
77- return False
62+ print ("Already connected to Wi-Fi. IP: " + self .wlan_sta .ifconfig ()[0 ])
63+ self .wlan_sta .disconnect ()
64+ self .wlan_sta .active (False )
65+ #time.sleep(1)
66+ await asyncio .sleep (1 )
67+ print ("Disconnected from Wi-Fi." )
68+ else :
69+ print ("Not connected to Wi-Fi." )
70+
71+ # Activate Wi-Fi mode and connect
72+ self .wlan_sta .active (True )
73+ #time.sleep(1)
74+ await asyncio .sleep (1 )
75+ self .wlan_sta .connect (ssid , password )
76+ # Wait for connection
77+ print ("Connecting to Wi-Fi..." )
78+ for _ in range (self .timeout ):
79+ #time.sleep(1)
80+ await asyncio .sleep (1 )
81+ if self .wlan_sta .isconnected ():
82+ self .ip_address = self .wlan_sta .ifconfig ()[0 ]
83+ print (f"Connected to Wi-Fi. IP: { self .ip_address } " )
84+ return True
85+ print ("Failed to connect to Wi-Fi." )
86+ return False
87+ except OSError as e :
88+ print (f"Error connecting to Wi-Fi: { e } " )
89+ return False
90+
91+ def is_wifi_connected (self ):
92+ return self .wlan_sta .isconnected ()
93+
94+ def is_access_point_active (self ):
95+ return self .wlan_ap .active ()
96+
97+ def get_wifi_ssid (self ):
98+ return self .wifi_ssid
99+
100+ def get_wifi_ip_address (self ):
101+ return self .wlan_sta .ifconfig ()[0 ]
102+
103+ def get_ap_ssid (self ):
104+ return self .wlan_ap .config ('essid' )
105+ return self .ap_ssid
106+
107+ def get_ap_ip_address (self ):
108+ return self .wlan_ap .ifconfig ()[0 ]
109+
110+ def get_ip_address (self ):
111+ return self .ip_address
78112
79113 def start_access_point (self , ssid , password = None ):
80114 #def connect_access_point(self, ssid, password=None, ip='192.168.1.1', subnet='255.255.255.0', gateway='192.168.1.1', dns='8.8.8.8'):
81115 # Set the IP configuration for the AP mode
82116 #self.wlan_ap.ifconfig((ip, subnet, gateway, dns))
83117 self .ap_ssid = ssid
84118 self .ap_password = password
85- self .wlan_ap .active (True ) # ESP32 needed this before config
119+ if os .uname ().sysname == 'esp32' :
120+ self .wlan_ap .active (True ) # ESP32 needed this before config
86121 self .wlan_ap .config (essid = ssid , password = password )
87- self .ip_address = self .wlan_ap .ifconfig ()[0 ]
88- print (f"AP Mode started. SSID: { ssid } , IP: { self .ip_address } " )
122+ if os .uname ().sysname != 'esp32' :
123+ self .wlan_ap .active (True )
124+ print (f"AP Mode started. SSID: { self .get_ap_ssid ()} , IP: { self .get_ap_ip_address ()} " )
125+ # pico needs a cycle or ssid is PICO-xxxx
126+ if self .get_ap_ssid () != ssid :
127+ print ("AP SSID incorrect: " + self .get_ap_ssid ())
128+ machine .reset ()
89129 return True
90130
91131 async def maintain_connection (self ):
92132 while True :
93133 if self .wlan_sta .isconnected () == False and self .wifi_ssid != None :
94134 print ("Lost connection to Wi-Fi. Attempting to reconnect..." )
95135 self .connect_wifi (self .wifi_ssid , self .wifi_password )
96- await asyncio .sleep (10 )
136+ await asyncio .sleep (20 )
97137
98138
99139 async def start_server (self ):
@@ -121,6 +161,9 @@ async def main():
121161 def set_default_index_pages (self , default_index_pages ):
122162 self .default_index_pages = default_index_pages
123163
164+ def set_cors (self , enable_cors = True ):
165+ self .enable_cors = enable_cors
166+
124167 # async def start_server(self):
125168 # print("start_server")
126169 # server = await asyncio.start_server(
@@ -134,7 +177,7 @@ def add_function_route(self, route, function):
134177 async def serve_request (self , reader , writer ):
135178 gc .collect ()
136179 try :
137- response = Response (writer )
180+ response = Response (writer , enable_cors = self . enable_cors )
138181 url = ""
139182 method = ""
140183 content_length = 0
@@ -149,39 +192,50 @@ async def serve_request(self, reader, writer):
149192 break
150193 headers .append (line )
151194 request_raw = str ("\r \n " .join (headers ))
152- print (request_raw )
153- request_pattern = re .compile (r"(GET|POST)\s+([^\s]+)\s+HTTP" )
195+ if self .log_level > 0 :
196+ print (request_raw )
197+ request_pattern = re .compile (r"(GET|POST|OPTIONS)\s+([^\s]+)\s+HTTP" )
154198 match = request_pattern .search (request_raw )
155199 if match :
156200 method = match .group (1 )
157201 url = match .group (2 )
158- print (method , url )
202+ if self .log_level > 0 :
203+ print (method , url )
159204 else : # regex didn't match, try splitting the request line
160205 request_parts = request_raw .split (" " )
161206 if len (request_parts ) > 1 :
162207 method = request_parts [0 ]
163208 url = request_parts [1 ]
164- print (method , url )
165- else :
209+ if self .log_level > 0 :
210+ print (method , url )
211+ elif self .log_level > 0 :
166212 print ("no match" )
213+ if method == "OPTIONS" :
214+ # Handle preflight requests
215+ await response .send ("" , status_code = 204 )
216+ return
167217 # extract content length for POST requests
168218 if method == "POST" :
169219 content_length_pattern = re .compile (r"Content-Length:\s+(\d+)" )
170220 match = content_length_pattern .search (request_raw )
171221 if match :
172222 content_length = int (match .group (1 ))
173- print ("content_length: " + str (content_length ))
223+ if self .log_level > 0 :
224+ print ("content_length: " + str (content_length ))
174225 # Read the POST data if there's any
175226 if content_length > 0 :
176227 post_data_raw = await reader .readexactly (content_length )
177- print ("POST data:" , post_data_raw )
228+ if self .log_level > 0 :
229+ print ("POST data:" , post_data_raw )
178230 content_type_header = "Content-Type: application/json" # default to JSON
179231 for header in headers :
180232 if header .lower ().startswith ("content-type:" ):
181233 content_type_header = header
182234 break
183235 if "application/json" in content_type_header .lower ():
184236 try :
237+ if self .log_level > 0 :
238+ print ("decoding JSON data" )
185239 post_data = json .loads (post_data_raw )
186240 except ValueError as e :
187241 print ("Error decoding JSON data:" , e )
@@ -222,6 +276,7 @@ async def serve_request(self, reader, writer):
222276 if self .log_level > 1 :
223277 print ("index_file_path: " + str (index_file_path ))
224278 if self .file_exists (index_file_path ):
279+ print ("serving index file: " + index_file_path )
225280 await response .send_file (index_file_path , content_type = self .get_content_type (index_file_path ))
226281 return
227282 files_and_folders = self .list_files_and_folders (file_path )
0 commit comments