-
-
Notifications
You must be signed in to change notification settings - Fork 345
/
application.cpp
179 lines (144 loc) · 4.83 KB
/
application.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include <SmingCore.h>
#include <Network/Http/Websocket/WebsocketResource.h>
#include "CUserData.h"
#ifdef ENABLE_CMD_HANDLER
#include <CommandProcessing/Handler.h>
CommandProcessing::Handler commandHandler;
#endif
// If you want, you can define WiFi settings globally in Eclipse Environment Variables
#ifndef WIFI_SSID
#define WIFI_SSID "PleaseEnterSSID" // Put your SSID and password here
#define WIFI_PWD "PleaseEnterPass"
#endif
namespace
{
HttpServer server;
unsigned totalActiveSockets;
CUserData userGeorge;
void onIndex(HttpRequest& request, HttpResponse& response)
{
auto tmpl = new TemplateFileStream(F("index.html"));
//auto& vars = tmpl->variables();
//vars["counter"] = String(counter);
response.sendNamedStream(tmpl); // this template object will be deleted automatically
}
void onFile(HttpRequest& request, HttpResponse& response)
{
String file = request.uri.getRelativePath();
if(file[0] == '.') {
response.code = HTTP_STATUS_FORBIDDEN;
} else {
response.setCache(86400, true); // It's important to use cache for better performance.
response.sendFile(file);
}
}
void shutdownServer()
{
// Don't shutdown immediately, wait a bit to allow messages to propagate
auto timer = new AutoDeleteTimer;
timer->initializeMs<1000>([&]() { server.shutdown(); });
timer->startOnce();
}
void wsConnected(WebsocketConnection& socket)
{
totalActiveSockets++;
//Use a global instance and add this new connection. Normally
userGeorge.addSession(socket);
// Notify everybody about new connection
String message = F("New friend arrived! Total: ") + String(totalActiveSockets);
socket.broadcast(message);
}
void wsMessageReceived(WebsocketConnection& socket, const String& message)
{
Serial.println(_F("WebSocket message received:"));
Serial.println(message);
if(message == _F("shutdown")) {
String message(F("The server is shutting down..."));
socket.broadcast(message);
shutdownServer();
return;
}
String response = F("Echo: ") + message;
socket.sendString(response);
// Normally you would use dynamic cast but just be careful not to convert to wrong object type!
auto user = static_cast<CUserData*>(socket.getUserData());
if(user != nullptr) {
user->printMessage(socket, message);
}
}
#ifdef ENABLE_CMD_HANDLER
void wsCommandReceived(WebsocketConnection& socket, const String& message)
{
debug_i("%s(%s)", __FUNCTION__, message.c_str());
String response = commandHandler.processNow(message.c_str(), message.length());
socket.sendString(response);
// Normally you would use dynamic cast but just be careful not to convert to wrong object type!
auto user = static_cast<CUserData*>(socket.getUserData());
if(user != nullptr) {
user->printMessage(socket, message);
}
}
void processShutdownCommand(String commandLine, ReadWriteStream& commandOutput)
{
shutdownServer();
}
#endif
void wsBinaryReceived(WebsocketConnection& socket, uint8_t* data, size_t size)
{
Serial << _F("Websocket binary data received, size: ") << size << endl;
}
void wsDisconnected(WebsocketConnection& socket)
{
totalActiveSockets--;
// Normally you would use dynamic cast but just be careful not to convert to wrong object type!
auto user = static_cast<CUserData*>(socket.getUserData());
if(user != nullptr) {
user->removeSession(socket);
}
// Notify everybody about lost connection
String message = F("We lost our friend :( Total: ") + String(totalActiveSockets);
socket.broadcast(message);
}
void startWebServer()
{
server.listen(80);
server.paths.set("/", onIndex);
server.paths.setDefault(onFile);
// Web Sockets configuration
auto wsResource = new WebsocketResource();
wsResource->setConnectionHandler(wsConnected);
wsResource->setMessageHandler(wsMessageReceived);
#ifdef ENABLE_CMD_HANDLER
wsResource->setMessageHandler(wsCommandReceived);
#endif
wsResource->setBinaryHandler(wsBinaryReceived);
wsResource->setDisconnectionHandler(wsDisconnected);
server.paths.set("/ws", wsResource);
Serial.println(_F("\r\n"
"=== WEB SERVER STARTED ==="));
Serial.println(WifiStation.getIP());
Serial.println(_F("==========================\r\n"));
}
// Will be called when WiFi station becomes fully operational
void gotIP(IpAddress ip, IpAddress netmask, IpAddress gateway)
{
startWebServer();
}
} // namespace
void init()
{
spiffs_mount(); // Mount file system, in order to work with files
#ifdef ENABLE_CMD_HANDLER
commandHandler.registerSystemCommands();
commandHandler.registerCommand(
{CMDP_STRINGS("shutdown", "Shutdown Server Command", "Application"), processShutdownCommand});
#endif
userGeorge = CUserData{F("George"), F("I like SMING")};
Serial.begin(SERIAL_BAUD_RATE); // 115200 by default
Serial.systemDebugOutput(true); // Enable debug output to serial
WifiStation.enable(true);
WifiStation.config(F(WIFI_SSID), F(WIFI_PWD));
WifiAccessPoint.enable(false);
// Run our method when station was connected to AP
WifiEvents.onStationGotIP(gotIP);
}