Skip to content

Commit a0a0bc2

Browse files
committed
..
1 parent 221e6e1 commit a0a0bc2

File tree

3 files changed

+243
-9
lines changed

3 files changed

+243
-9
lines changed
3.01 MB
Binary file not shown.
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# 1 "C:\\Users\\TOLENT~1\\AppData\\Local\\Temp\\tmp0o5smhuc"
2+
#include <Arduino.h>
3+
# 1 "C:/Users/Tolentino/Documents/Arduino/libraries/async-esp-fs-webserver/pio_examples/withWebSocket/src/withWebSocket.ino"
4+
#include <FS.h>
5+
#include <LittleFS.h>
6+
#include "AsyncFsWebServer.h"
7+
8+
#include "index_htm.h"
9+
10+
#define FILESYSTEM LittleFS
11+
12+
char const* hostname = "fsbrowser";
13+
AsyncFsWebServer server(80, FILESYSTEM, hostname);
14+
15+
#ifndef LED_BUILTIN
16+
#define LED_BUILTIN 2
17+
#endif
18+
#define BOOT_BUTTON 0
19+
void wsLogPrintf(bool toSerial, const char* format, ...);
20+
void onWsEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
21+
void getUpdatedtime(const uint32_t timeout);
22+
bool startFilesystem();
23+
bool loadApplicationConfig();
24+
void setup();
25+
void loop();
26+
#line 18 "C:/Users/Tolentino/Documents/Arduino/libraries/async-esp-fs-webserver/pio_examples/withWebSocket/src/withWebSocket.ino"
27+
void wsLogPrintf(bool toSerial, const char* format, ...) {
28+
char buffer[128];
29+
va_list args;
30+
va_start(args, format);
31+
vsnprintf(buffer, 128, format, args);
32+
va_end(args);
33+
server.wsBroadcast(buffer);
34+
if (toSerial)
35+
Serial.println(buffer);
36+
}
37+
38+
39+
void onWsEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len) {
40+
switch (type) {
41+
case WS_EVT_CONNECT:
42+
client->printf("{\"Websocket connected\": true, \"clients\": %u}", client->id());
43+
Serial.printf("Websocket client %u connected\n", client->id());
44+
break;
45+
46+
case WS_EVT_DISCONNECT:
47+
Serial.printf("Websocket client %u connected\n", client->id());
48+
break;
49+
50+
case WS_EVT_DATA:
51+
{
52+
AwsFrameInfo* info = (AwsFrameInfo*)arg;
53+
if (info->opcode == WS_TEXT) {
54+
char msg[len+1];
55+
msg[len] = '\0';
56+
memcpy(msg, data, len);
57+
Serial.printf("Received message \"%s\"\n", msg);
58+
}
59+
}
60+
break;
61+
62+
default:
63+
break;
64+
}
65+
}
66+
67+
68+
String option1 = "Test option String";
69+
uint32_t option2 = 1234567890;
70+
uint8_t ledPin = LED_BUILTIN;
71+
72+
73+
#define MYTZ "CET-1CEST,M3.5.0,M10.5.0/3"
74+
struct tm Time;
75+
76+
77+
78+
void getUpdatedtime(const uint32_t timeout) {
79+
uint32_t start = millis();
80+
Serial.print("Sync time...");
81+
while (millis() - start < timeout && Time.tm_year <= (1970 - 1900)) {
82+
time_t now = time(nullptr);
83+
Time = *localtime(&now);
84+
delay(5);
85+
}
86+
Serial.println(" done.");
87+
}
88+
89+
90+
91+
bool startFilesystem() {
92+
if (FILESYSTEM.begin()) {
93+
server.printFileList(FILESYSTEM, "/", 1, Serial);
94+
return true;
95+
} else {
96+
Serial.println("ERROR on mounting filesystem. It will be reformatted!");
97+
FILESYSTEM.format();
98+
ESP.restart();
99+
}
100+
return false;
101+
}
102+
103+
104+
105+
bool loadApplicationConfig() {
106+
if (FILESYSTEM.exists(server.getConfiFileName())) {
107+
File file = server.getConfigFile("r");
108+
String content = file.readString();
109+
file.close();
110+
AsyncFSWebServer::Json json;
111+
if (!json.parse(content)) {
112+
Serial.println(F("Failed to parse JSON configuration."));
113+
return false;
114+
}
115+
String str;
116+
double num;
117+
if (json.getString("Option 1", str)) option1 = str;
118+
if (json.getNumber("Option 2", num)) option2 = (uint32_t)num;
119+
if (json.getNumber("LED Pin", num)) ledPin = (uint8_t)num;
120+
return true;
121+
}
122+
return false;
123+
}
124+
125+
126+
void setup() {
127+
pinMode(LED_BUILTIN, OUTPUT);
128+
pinMode(BOOT_BUTTON, INPUT_PULLUP);
129+
130+
Serial.begin(115200);
131+
delay(1000);
132+
133+
134+
if (startFilesystem()) {
135+
136+
if (loadApplicationConfig()) {
137+
Serial.println(F("\nApplication option loaded"));
138+
Serial.printf(" LED Pin: %d\n", ledPin);
139+
Serial.printf(" Option 1: %s\n", option1.c_str());
140+
Serial.printf(" Option 2: %u\nn", option2);
141+
}
142+
else
143+
Serial.println(F("Application options NOT loaded!"));
144+
}
145+
146+
147+
if (!server.startWiFi(10000)) {
148+
Serial.println("\nWiFi not connected! Starting AP mode...");
149+
server.startCaptivePortal("ESP_AP", "123456789", "/setup");
150+
}
151+
152+
153+
server.addOptionBox("My Options");
154+
server.addOption("LED Pin", ledPin);
155+
server.addOption("Option 1", option1.c_str());
156+
server.addOption("Option 2", option2);
157+
158+
159+
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
160+
request->send(200, "text/html", homepage);
161+
});
162+
163+
164+
server.enableFsCodeEditor();
165+
166+
167+
168+
169+
170+
#ifdef ESP32
171+
server.setFsInfoCallback([](fsInfo_t* fsInfo) {
172+
fsInfo->fsName = "LittleFS";
173+
fsInfo->totalBytes = LittleFS.totalBytes();
174+
fsInfo->usedBytes = LittleFS.usedBytes();
175+
});
176+
#endif
177+
178+
179+
server.init(onWsEvent);
180+
181+
Serial.print(F("ESP Web Server started on IP Address: "));
182+
Serial.println(server.getServerIP());
183+
Serial.println(F(
184+
"This is \"withWebSocket.ino\" example.\n"
185+
"Open /setup page to configure optional parameters.\n"
186+
"Open /edit page to view, edit or upload example or your custom webserver source files."
187+
));
188+
189+
190+
WiFi.setHostname(hostname);
191+
configTzTime(MYTZ, "time.google.com", "time.windows.com", "pool.ntp.org");
192+
193+
194+
if (WiFi.status() == WL_CONNECTED) {
195+
if (MDNS.begin(hostname)) {
196+
Serial.println(F("MDNS responder started."));
197+
Serial.printf("You should be able to connect with address http://%s.local/\n", hostname);
198+
199+
MDNS.addService("http", "tcp", 80);
200+
}
201+
}
202+
}
203+
204+
205+
void loop() {
206+
207+
if (digitalRead(BOOT_BUTTON) == LOW) {
208+
wsLogPrintf(true, "Button on GPIO %d clicked", BOOT_BUTTON);
209+
delay(1000);
210+
}
211+
212+
213+
static uint32_t sendToClientTime;
214+
if (millis() - sendToClientTime > 1000) {
215+
sendToClientTime = millis();
216+
time_t now = time(nullptr);
217+
wsLogPrintf(false, "{\"esptime\": %d}", (int)now);
218+
}
219+
220+
delay(10);
221+
}

src/AsyncFsWebServer.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,22 +39,21 @@ bool AsyncFsWebServer::init(AwsEventHandler wsHandle) {
3939
on("/scan", HTTP_GET, [this](AsyncWebServerRequest *request) { this->handleScanNetworks(request); });
4040
on("/getStatus", HTTP_GET, [this](AsyncWebServerRequest *request) { this->getStatus(request); });
4141
on("/clear_config", HTTP_GET, [this](AsyncWebServerRequest *request) { this->clearConfig(request); });
42-
43-
42+
// Simple WiFi status endpoint
4443
on("/wifi", HTTP_GET, [](AsyncWebServerRequest *request) {
4544
AsyncFSWebServer::Json doc;
4645
doc.setString("ssid", WiFi.SSID());
4746
doc.setNumber("rssi", WiFi.RSSI());
4847
request->send(200, "application/json", doc.serialize());
4948
});
50-
49+
// File upload handler for configuration files
5150
on("/upload", HTTP_POST,
5251
[this](AsyncWebServerRequest *request) { this->sendOK(request); },
5352
[this](AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final) {
5453
this->handleUpload(request, filename, index, data, len, final);
5554
}
5655
);
57-
56+
// Endpoint to reset device
5857
on("/reset", HTTP_GET, [](AsyncWebServerRequest *request) {
5958
// Send response and restart AFTER client disconnects to ensure 200 reaches browser
6059
AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", WiFi.localIP().toString());
@@ -208,14 +207,28 @@ void AsyncFsWebServer::sendOK(AsyncWebServerRequest *request) {
208207
}
209208

210209
void AsyncFsWebServer::notFound(AsyncWebServerRequest *request) {
211-
if (request->url() == "/" && !m_filesystem->exists("/index.htm") && !m_filesystem->exists("/index.html")) {
212-
request->redirect("/setup");
213-
log_debug("Redirecting \"/\" to \"/setup\" (no index file found)");
210+
String _url = request->url();
211+
212+
// Requested file not found, check if gzipped version exists
213+
_url += ".gz";
214+
if (!m_filesystem->exists(_url)) {
215+
log_debug("File %s not found, checking for index redirection", request->url().c_str());
216+
217+
// File not found
218+
if (request->url() == "/" && !m_filesystem->exists("/index.htm") && !m_filesystem->exists("/index.html")) {
219+
request->redirect("/setup");
220+
log_debug("Redirecting \"/\" to \"/setup\" (no index file found)");
221+
return;
222+
}
214223
}
215224
else {
216-
request->send(404, "text/plain", "AsyncFsWebServer: resource not found");
217-
log_debug("Resource %s not found\n", request->url().c_str());
225+
log_debug("Serving gzipped file for %s", request->url().c_str());
226+
request->redirect(_url);
227+
return;
218228
}
229+
230+
request->send(404, "text/plain", "AsyncFsWebServer: resource not found");
231+
log_debug("Resource %s not found", request->url().c_str());
219232
}
220233

221234

0 commit comments

Comments
 (0)