Skip to content

Commit d8bbff2

Browse files
committed
pulled in many improvements from the wordclock
1 parent e4b2625 commit d8bbff2

File tree

1 file changed

+91
-36
lines changed

1 file changed

+91
-36
lines changed

src/gurgleapps_webserver.py

Lines changed: 91 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from request import Request
1616
import gc
1717
import os
18+
import machine
1819

1920

2021
class 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

Comments
 (0)