| 2 |
raymond |
1 |
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
|
2 |
// Copyright 2016-2026 Hristo Gochkov, Mathieu Carbou, Emil Muratov, Will Miles
|
|
|
3 |
|
|
|
4 |
//
|
|
|
5 |
// WebSocket example
|
|
|
6 |
//
|
|
|
7 |
|
|
|
8 |
#include <Arduino.h>
|
|
|
9 |
#include <AsyncTCP.h>
|
|
|
10 |
#include <WiFi.h>
|
|
|
11 |
|
|
|
12 |
#include <ESPAsyncWebServer.h>
|
|
|
13 |
|
|
|
14 |
static AsyncWebServer server(80);
|
|
|
15 |
static AsyncWebSocket ws("/ws");
|
|
|
16 |
|
|
|
17 |
void setup() {
|
|
|
18 |
Serial.begin(115200);
|
|
|
19 |
|
|
|
20 |
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED || LT_ARD_HAS_WIFI || CONFIG_ESP32_WIFI_ENABLED
|
|
|
21 |
WiFi.mode(WIFI_AP);
|
|
|
22 |
WiFi.softAP("esp-captive");
|
|
|
23 |
#endif
|
|
|
24 |
|
|
|
25 |
//
|
|
|
26 |
// Run in terminal 1: websocat ws://192.168.4.1/ws => should stream data
|
|
|
27 |
// Run in terminal 2: websocat ws://192.168.4.1/ws => should stream data
|
|
|
28 |
// Run in terminal 3: websocat ws://192.168.4.1/ws => should fail:
|
|
|
29 |
//
|
|
|
30 |
// To send a message to the WebSocket server:
|
|
|
31 |
//
|
|
|
32 |
// echo "Hello!" | websocat ws://192.168.4.1/ws
|
|
|
33 |
//
|
|
|
34 |
ws.onEvent([](AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
|
|
|
35 |
(void)len;
|
|
|
36 |
|
|
|
37 |
if (type == WS_EVT_CONNECT) {
|
|
|
38 |
ws.textAll("new client connected");
|
|
|
39 |
Serial.println("ws connect");
|
|
|
40 |
client->ping();
|
|
|
41 |
|
|
|
42 |
} else if (type == WS_EVT_DISCONNECT) {
|
|
|
43 |
ws.textAll("client disconnected");
|
|
|
44 |
Serial.println("ws disconnect");
|
|
|
45 |
|
|
|
46 |
} else if (type == WS_EVT_ERROR) {
|
|
|
47 |
Serial.println("ws error");
|
|
|
48 |
|
|
|
49 |
} else if (type == WS_EVT_PONG) {
|
|
|
50 |
Serial.println("ws pong");
|
|
|
51 |
|
|
|
52 |
} else if (type == WS_EVT_DATA) {
|
|
|
53 |
AwsFrameInfo *info = (AwsFrameInfo *)arg;
|
|
|
54 |
String msg = "";
|
|
|
55 |
if (info->final && info->index == 0 && info->len == len) {
|
|
|
56 |
if (info->message_opcode == WS_TEXT) {
|
|
|
57 |
Serial.printf("ws text: %s\n", (char *)data);
|
|
|
58 |
}
|
|
|
59 |
}
|
|
|
60 |
}
|
|
|
61 |
});
|
|
|
62 |
|
|
|
63 |
// shows how to prevent a third WS client to connect
|
|
|
64 |
server.addHandler(&ws).addMiddleware([](AsyncWebServerRequest *request, ArMiddlewareNext next) {
|
|
|
65 |
// ws.count() is the current count of WS clients: this one is trying to upgrade its HTTP connection
|
|
|
66 |
if (ws.count() > 1) {
|
|
|
67 |
// if we have 2 clients or more, prevent the next one to connect
|
|
|
68 |
request->send(503, "text/plain", "Server is busy");
|
|
|
69 |
} else {
|
|
|
70 |
// process next middleware and at the end the handler
|
|
|
71 |
next();
|
|
|
72 |
}
|
|
|
73 |
});
|
|
|
74 |
|
|
|
75 |
server.addHandler(&ws);
|
|
|
76 |
|
|
|
77 |
server.begin();
|
|
|
78 |
}
|
|
|
79 |
|
|
|
80 |
static uint32_t lastWS = 0;
|
|
|
81 |
static uint32_t deltaWS = 100;
|
|
|
82 |
|
|
|
83 |
static uint32_t lastHeap = 0;
|
|
|
84 |
|
|
|
85 |
void loop() {
|
|
|
86 |
uint32_t now = millis();
|
|
|
87 |
|
|
|
88 |
if (now - lastWS >= deltaWS) {
|
|
|
89 |
ws.printfAll("kp%.4f", (10.0 / 3.0));
|
|
|
90 |
lastWS = millis();
|
|
|
91 |
}
|
|
|
92 |
|
|
|
93 |
if (now - lastHeap >= 2000) {
|
|
|
94 |
// cleanup disconnected clients or too many clients
|
|
|
95 |
ws.cleanupClients();
|
|
|
96 |
|
|
|
97 |
Serial.printf("Free heap: %" PRIu32 "\n", ESP.getFreeHeap());
|
|
|
98 |
lastHeap = now;
|
|
|
99 |
}
|
|
|
100 |
}
|