Skip to content

Commit f0878dc

Browse files
authored
Add support for Teensy 4.1 (#93)
* Add support for Teensy 4.1 * Add examples for Teensy 4.1 * Simplify Teensy 4.1 example * Update readme * Fix typo
1 parent ddab1a9 commit f0878dc

File tree

8 files changed

+698
-1
lines changed

8 files changed

+698
-1
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ The library provides simple and easy interface for websockets work (Client and S
1212
This section should help you get started with the library. If you have any questions feel free to open an issue.
1313

1414
### Prerequisites
15-
Currently (version 0.4.*) the library only works with `ESP8266` and `ESP32`.
15+
Currently (version 0.4.*) the library only works with `ESP8266`, `ESP32` and `Teensy 4.1`.
1616

1717
### Installing
1818

@@ -254,6 +254,9 @@ const char ssl_ca_cert[] PROGMEM = \
254254
client.setCACert(ssl_ca_cert);
255255
```
256256

257+
### TEENSY 4.1
258+
Currently WSS is not implemented.
259+
257260
## Contributing
258261
Contributions are welcomed! Please open issues if you have troubles while using the library or any queshtions on how to get started. Pull requests are welcomed, please open an issue first.
259262

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
Teensy41 Websockets Server and Http Server (using NativeEthernet).
3+
Combining the Teensy41-Server example with the NativeEthernet WebServer
4+
example (https://github.com/vjmuzik/NativeEthernet/blob/master/examples/WebServer/WebServer.ino).
5+
6+
This sketch:
7+
1. Connects to a ethernet network
8+
2. Starts a websocket server on port 80
9+
3. Waits for connections
10+
4. As soon as a client wants to establish a connection, it checks whether a
11+
free slot is available and accepts it accordingly
12+
5. If the client is accepted it sends a welcome message and echoes any
13+
messages from the client
14+
6. Goes back to step 3
15+
16+
Note:
17+
Make sure you share your computer's internet connection with the Teensy
18+
via ethernet.
19+
20+
Libraries:
21+
To use this sketch install
22+
* TeensyID library (https://github.com/sstaub/TeensyID)
23+
* NativeEthernet (https://github.com/vjmuzik/NativeEthernet)
24+
25+
Hardware:
26+
For this sketch you need a Teensy 4.1 board and the Teensy 4.1 Ethernet Kit
27+
(https://www.pjrc.com/store/ethernet_kit.html).
28+
*/
29+
30+
#include <NativeEthernet.h>
31+
#include <ArduinoWebsockets.h>
32+
#include <TeensyID.h>
33+
34+
using namespace websockets;
35+
36+
// We will set the MAC address at the beginning of `setup()` using TeensyID's
37+
// `teensyMac` helper.
38+
byte mac[6];
39+
40+
// Enter websockets server port.
41+
const uint16_t port = 80;
42+
43+
// Define how many clients we accpet simultaneously.
44+
const byte maxClients = 4;
45+
46+
WebsocketsClient clients[maxClients];
47+
WebsocketsServer server;
48+
49+
void setup() {
50+
// Set the MAC address.
51+
teensyMAC(mac);
52+
53+
// Connect to ethernet.
54+
if (Ethernet.begin(mac)) {
55+
Serial.println("Ethernet connected");
56+
} else {
57+
Serial.println("Ethernet failed");
58+
}
59+
60+
// Start websockets server.
61+
server.listen(port);
62+
if (server.available()) {
63+
Serial.print("Server available at ws://");
64+
Serial.print(Ethernet.localIP());
65+
// Also log any non default port.
66+
if (port != 80) Serial.printf(":%d", port);
67+
Serial.println();
68+
} else {
69+
Serial.println("Server not available!");
70+
}
71+
}
72+
73+
void handleMessage(WebsocketsClient &client, WebsocketsMessage message) {
74+
auto data = message.data();
75+
76+
// Log message
77+
Serial.print("Got Message: ");
78+
Serial.println(data);
79+
80+
// Echo message
81+
client.send("Echo: " + data);
82+
}
83+
84+
void handleEvent(WebsocketsClient &client, WebsocketsEvent event, String data) {
85+
if (event == WebsocketsEvent::ConnectionClosed) {
86+
Serial.println("Connection closed");
87+
}
88+
}
89+
90+
int8_t getFreeClientIndex() {
91+
// If a client in our list is not available, it's connection is closed and we
92+
// can use it for a new client.
93+
for (byte i = 0; i < maxClients; i++) {
94+
if (!clients[i].available()) return i;
95+
}
96+
return -1;
97+
}
98+
99+
void listenForClients() {
100+
if (server.poll()) {
101+
int8_t freeIndex = getFreeClientIndex();
102+
if (freeIndex >= 0) {
103+
WebsocketsClient newClient = server.accept();
104+
Serial.printf("Accepted new websockets client at index %d\n", freeIndex);
105+
newClient.onMessage(handleMessage);
106+
newClient.onEvent(handleEvent);
107+
newClient.send("Hello from Teensy");
108+
clients[freeIndex] = newClient;
109+
}
110+
}
111+
}
112+
113+
void pollClients() {
114+
for (byte i = 0; i < maxClients; i++) {
115+
clients[i].poll();
116+
}
117+
}
118+
119+
void loop() {
120+
listenForClients();
121+
pollClients();
122+
}
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
/*
2+
Teensy41 Websockets Server and Http Server (using NativeEthernet).
3+
Combining the Teensy41-Server-Multiple-Clients example with the NativeEthernet
4+
WebServer example (https://github.com/vjmuzik/NativeEthernet/blob/master/examples/WebServer/WebServer.ino).
5+
6+
This sketch:
7+
1. Connects to a ethernet network
8+
2. Starts a websocket server on port 3000
9+
3. Starts a http server at the default port 80
10+
4. Waits for both http and websockets connections
11+
5. Once a http client connects, it serves an html document, once a socket
12+
client wants to connect, it checks whether a free slot is available and
13+
accepts it accordingly
14+
5. If the socket client is accepted it sends a welcome message and echoes any
15+
messages from the client
16+
6. Goes back to step 4
17+
18+
Note:
19+
Make sure you share your computer's internet connection with the Teensy
20+
via ethernet.
21+
22+
Libraries:
23+
To use this sketch install
24+
* TeensyID library (https://github.com/sstaub/TeensyID)
25+
* NativeEthernet (https://github.com/vjmuzik/NativeEthernet)
26+
27+
Hardware:
28+
For this sketch you need a Teensy 4.1 board and the Teensy 4.1 Ethernet Kit
29+
(https://www.pjrc.com/store/ethernet_kit.html).
30+
*/
31+
32+
#include <NativeEthernet.h>
33+
#include <ArduinoWebsockets.h>
34+
#include <TeensyID.h>
35+
36+
using namespace websockets;
37+
38+
// We will set the MAC address at the beginning of `setup()` using TeensyID's
39+
// `teensyMac` helper.
40+
byte mac[6];
41+
42+
// Enter websockets server port.
43+
const uint16_t websocketsPort = 3000;
44+
45+
// Define how many clients we accpet simultaneously.
46+
const byte maxSocketClients = 4;
47+
48+
WebsocketsClient socketClients[maxSocketClients];
49+
WebsocketsServer socketServer;
50+
EthernetServer httpServer;
51+
52+
void setup() {
53+
// Set the MAC address.
54+
teensyMAC(mac);
55+
56+
// Start Serial and wait until it is ready.
57+
Serial.begin(9600);
58+
while (!Serial) {}
59+
60+
// Connect to ethernet.
61+
if (Ethernet.begin(mac)) {
62+
Serial.println("Ethernet connected");
63+
} else {
64+
Serial.println("Ethernet failed");
65+
}
66+
67+
// Start websockets server.
68+
socketServer.listen(websocketsPort);
69+
if (!socketServer.available()) {
70+
Serial.println("Websockets Server not available!");
71+
}
72+
73+
// Start http server.
74+
httpServer.begin(80);
75+
Serial.print("Visit http://");
76+
Serial.print(Ethernet.localIP());
77+
Serial.println(" in the browser to connect.");
78+
}
79+
80+
int8_t getFreeSocketClientIndex() {
81+
// If a client in our list is not available, it's connection is closed and we
82+
// can use it for a new client.
83+
for (byte i = 0; i < maxSocketClients; i++) {
84+
if (!socketClients[i].available()) return i;
85+
}
86+
return -1;
87+
}
88+
89+
void handleMessage(WebsocketsClient &client, WebsocketsMessage message) {
90+
auto data = message.data();
91+
92+
// Log message
93+
Serial.print("Got Message: ");
94+
Serial.println(data);
95+
96+
// Echo message
97+
client.send("Echo: " + data);
98+
}
99+
100+
void handleEvent(WebsocketsClient &client, WebsocketsEvent event, String data) {
101+
if (event == WebsocketsEvent::ConnectionClosed) {
102+
Serial.println("Connection closed");
103+
}
104+
}
105+
106+
void listenForSocketClients() {
107+
if (socketServer.poll()) {
108+
int8_t freeIndex = getFreeSocketClientIndex();
109+
if (freeIndex >= 0) {
110+
WebsocketsClient newClient = socketServer.accept();
111+
Serial.printf("Accepted new websockets client at index %d\n", freeIndex);
112+
newClient.onMessage(handleMessage);
113+
newClient.onEvent(handleEvent);
114+
newClient.send("Hello from Teensy");
115+
socketClients[freeIndex] = newClient;
116+
}
117+
}
118+
}
119+
120+
void pollSocketClients() {
121+
for (byte i = 0; i < maxSocketClients; i++) {
122+
socketClients[i].poll();
123+
}
124+
}
125+
126+
void sendHttpReply(EthernetClient &client) {
127+
// Send a website that connects to the websocket server and allows to
128+
// communicate with the teensy.
129+
130+
const char* header =
131+
"HTTP/1.1 200 OK\r\n"
132+
"Content-Type: text/html\r\n"
133+
"Connection: close\r\n"
134+
"\r\n";
135+
136+
const char* document =
137+
"<!DOCTYPE html>\n"
138+
"<title>Teensy 4.1 Websockets</title>\n"
139+
"<meta charset='UTF-8'>\n"
140+
"<style>\n"
141+
" body {\n"
142+
" display: grid;\n"
143+
" grid-template: min-content auto / auto min-content;\n"
144+
" grid-gap: 1em;\n"
145+
" margin: 0;\n"
146+
" padding: 1em;\n"
147+
" height: 100vh;\n"
148+
" box-sizing: border-box;\n"
149+
" }\n"
150+
" #output {\n"
151+
" grid-column-start: span 2;\n"
152+
" overflow-y: scroll;\n"
153+
" padding: 0.1em;\n"
154+
" border: 1px solid;\n"
155+
" font-family: monospace;\n"
156+
" }\n"
157+
"</style>\n"
158+
"<input type='text' id='message' placeholder='Send a message and Teensy will echo it back!'>\n"
159+
"<button id='send-message'>send</button>\n"
160+
"<div id='output'></div>\n"
161+
"<script>\n"
162+
" const url = `ws://${window.location.host}:3000`\n"
163+
" const ws = new WebSocket(url)\n"
164+
" let connected = false\n"
165+
" const sendMessage = document.querySelector('#send-message')\n"
166+
" const message = document.querySelector('#message')\n"
167+
" const output = document.querySelector('#output')\n"
168+
" function log(message, color = 'black') {\n"
169+
" const el = document.createElement('div')\n"
170+
" el.innerHTML = message\n"
171+
" el.style.color = color\n"
172+
" output.append(el)\n"
173+
" output.scrollTop = output.scrollHeight\n"
174+
" }\n"
175+
" ws.addEventListener('open', () => {\n"
176+
" connected = true\n"
177+
" log('(✔️) Open', 'green')\n"
178+
" })\n"
179+
" ws.addEventListener('close', () => {\n"
180+
" connected = false\n"
181+
" log('(❌) Close', 'red')\n"
182+
" })\n"
183+
" ws.addEventListener('message', ({ data }) =>\n"
184+
" log(`(💌) ${data}`)\n"
185+
" )\n"
186+
" sendMessage.addEventListener('click', () => {\n"
187+
" connected && ws.send(message.value)\n"
188+
" })\n"
189+
" message.addEventListener('keyup', ({ keyCode }) => {\n"
190+
" connected && keyCode === 13 && ws.send(message.value)\n"
191+
" })\n"
192+
" log(`(📡) Connecting to ${url} ...`, 'blue')\n"
193+
"</script>\n";
194+
195+
client.write(header);
196+
client.write(document);
197+
}
198+
199+
void listenForHttpClients() {
200+
// Listen for incoming http clients.
201+
EthernetClient client = httpServer.available();
202+
203+
if (client) {
204+
Serial.println("Http client connected!");
205+
206+
// An http request ends with a blank line.
207+
bool currentLineIsBlank = true;
208+
209+
while (client.connected()) {
210+
if (client.available()) {
211+
char c = client.read();
212+
213+
if (c == '\n' && currentLineIsBlank) {
214+
// If we've gotten to the end of the line (received a newline
215+
// character) and the line is blank, the http request has ended,
216+
// so we can send a reply.
217+
sendHttpReply(client);
218+
break;
219+
} else if (c == '\n') {
220+
// Starting a new line.
221+
currentLineIsBlank = true;
222+
} else if (c != '\r') {
223+
// Read a character on the current line.
224+
currentLineIsBlank = false;
225+
}
226+
}
227+
}
228+
229+
// The NativeEthernet's WebServer example adds a small delay here. For me it
230+
// seems to work without the delay. Uncomment to following line if you have
231+
// issues connecting to the website in the browser.
232+
// delay(1);
233+
234+
// Close the connection.
235+
client.stop();
236+
}
237+
}
238+
239+
void loop() {
240+
listenForSocketClients();
241+
pollSocketClients();
242+
listenForHttpClients();
243+
}

0 commit comments

Comments
 (0)