├── examples
├── index.html
├── app.js
├── Hello_time.ino
├── HelloTime_ESP32.ino
├── Hello_Time_ESP8266.ino
└── Hello_time_sparkfun.ino
├── SocketIOClient.h
├── README.md
└── SocketIOClient.cpp
/examples/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/examples/app.js:
--------------------------------------------------------------------------------
1 | var util = require('util');
2 | var app = require('http').createServer(handler);
3 | var io = require('socket.io')(app);
4 | var fs = require('fs');
5 | app.listen(3484);
6 |
7 | function handler (req, res) {
8 | fs.readFile(__dirname + '/index.html',
9 | function (err, data) {
10 | if (err) {
11 | res.writeHead(500);
12 | return res.end('Error loading index.html');
13 | }
14 |
15 | res.writeHead(200);
16 | res.end(data);
17 | });
18 | }
19 | function ParseJson(jsondata) {
20 | try {
21 | return JSON.parse(jsondata);
22 | } catch (error) {
23 | return null;
24 | }
25 | }
26 | function sendTime() {
27 | io.sockets.emit('atime', { time: new Date().toJSON() });
28 | }
29 | io.on('connection', function (socket) {
30 | console.log("Connected");
31 | socket.emit('welcome', { message: 'Connected !!!!' });
32 | socket.on('connection', function (data) {
33 | console.log(data); });
34 | socket.on('atime', function (data) {
35 | sendTime();
36 | console.log(data);
37 | });
38 | socket.on('JSON', function (data) {
39 | // console.log(data);
40 | var jsonStr = JSON.stringify(data);
41 | var parsed = ParseJson(jsonStr);
42 | console.log(parsed);
43 | console.log(parsed.sensor);
44 | });
45 | socket.on('arduino', function (data) {
46 | io.sockets.emit('arduino', { message: 'R0' });
47 | console.log(data);
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/examples/Hello_time.ino:
--------------------------------------------------------------------------------
1 | #include "SocketIOClient.h"
2 | #include "Ethernet.h"
3 | #include "SPI.h"
4 |
5 | SocketIOClient client;
6 |
7 | byte mac[] = { 0xAA, 0x00, 0xBE, 0xEF, 0xFE, 0xEE };
8 | char hostname[] = "192.168.0.5";
9 | int port = 1234;
10 |
11 | extern String RID;
12 | extern String Rname;
13 | extern String Rcontent;
14 |
15 | unsigned long previousMillis = 0;
16 | long interval = 10000;
17 | void setup() {
18 | pinMode(10, OUTPUT); //for some ethernet shield on the mega : disables the SD and enables the W5100
19 | digitalWrite(10, LOW);
20 | pinMode(4, OUTPUT);
21 | digitalWrite(4, HIGH);
22 | Serial.begin(9600);
23 |
24 | Ethernet.begin(mac);
25 |
26 | if (!client.connect(hostname, port))
27 | Serial.println(F("Not connected."));
28 | if (client.connected())
29 | {
30 | client.send("connection", "message", "Connected !!!!");
31 | }
32 | else
33 | {
34 | Serial.println("Connection Error");
35 | while(1);
36 | }
37 | delay(1000);
38 | }
39 |
40 | void loop()
41 | {
42 | unsigned long currentMillis = millis();
43 | if(currentMillis - previousMillis > interval)
44 | {
45 | previousMillis = currentMillis;
46 | //client.heartbeat(0);
47 | client.send("atime", "message", "Time please?");
48 | }
49 | if (client.monitor())
50 | {
51 | Serial.println(RID);
52 | if (RID == "atime" && Rname == "time")
53 | {
54 | Serial.print("Time is ");
55 | Serial.println(Rcontent);
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/examples/HelloTime_ESP32.ino:
--------------------------------------------------------------------------------
1 | /*
2 | * This sketch sends data via HTTP GET requests to data.sparkfun.com service.
3 | *
4 | * You need to get streamId and privateKey at data.sparkfun.com and paste them
5 | * below. Or just customize this script to talk to other HTTP servers.
6 | *
7 | */
8 | #define ESP32
9 | #include
10 |
11 | SocketIOClient client;
12 | const char* ssid = "xxxxxxxxxxxxxxxxx";
13 | const char* password = "xxxxxxxxxxxxx";
14 |
15 | char host[] = "192.168.1.1";
16 | int port = 1234;
17 | extern String RID;
18 | extern String Rname;
19 | extern String Rcontent;
20 |
21 | unsigned long previousMillis = 0;
22 | long interval = 5000;
23 | unsigned long lastreply = 0;
24 | unsigned long lastsend = 0;
25 |
26 | void setup() {
27 | Serial.begin(115200);
28 | delay(10);
29 |
30 | // We start by connecting to a WiFi network
31 |
32 | Serial.println();
33 | Serial.println();
34 | Serial.print("Connecting to ");
35 | Serial.println(ssid);
36 |
37 | WiFi.begin(ssid, password);
38 |
39 | while (WiFi.status() != WL_CONNECTED) {
40 | delay(500);
41 | Serial.print(".");
42 | }
43 |
44 | Serial.println("");
45 | Serial.println("WiFi connected");
46 | Serial.println("IP address: ");
47 | Serial.println(WiFi.localIP());
48 |
49 | if (!client.connect(host, port)) {
50 | Serial.println("connection failed");
51 | return;
52 | }
53 | if (client.connected())
54 | {
55 | client.send("connection", "message", "Connected !!!!");
56 | }
57 | }
58 |
59 | void loop() {
60 | unsigned long currentMillis = millis();
61 | if (currentMillis - previousMillis > interval)
62 | {
63 | previousMillis = currentMillis;
64 | //client.heartbeat(0);
65 | Serial.print("************************************** ");
66 | Serial.println(lastsend);
67 | client.send("atime", "message", "Time please?");
68 | lastsend = millis();
69 | Serial.print("************************************** ");
70 | Serial.println(lastsend);
71 | }
72 | if (client.monitor())
73 | {
74 | lastreply = millis();
75 | Serial.println(RID);
76 | if (RID == "atime" && Rname == "time")
77 | {
78 | Serial.print("Il est ");
79 | Serial.println(Rcontent);
80 | }
81 | }
82 |
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/examples/Hello_Time_ESP8266.ino:
--------------------------------------------------------------------------------
1 | /*
2 | * This sketch sends data via HTTP GET requests to data.sparkfun.com service.
3 | *
4 | * You need to get streamId and privateKey at data.sparkfun.com and paste them
5 | * below. Or just customize this script to talk to other HTTP servers.
6 | *
7 | */
8 | #include
9 | #include
10 | #include
11 |
12 |
13 | StaticJsonBuffer<200> jsonBuffer;
14 |
15 |
16 | SocketIOClient client;
17 | const char* ssid = "SSID";
18 | const char* password = "WPA KEY";
19 |
20 | char host[] = "192.168.0.5";
21 | int port = 1234;
22 | extern String RID;
23 | extern String Rname;
24 | extern String Rcontent;
25 |
26 | unsigned long previousMillis = 0;
27 | long interval = 5000;
28 | unsigned long lastreply = 0;
29 | unsigned long lastsend = 0;
30 | String JSON;
31 | JsonObject& root = jsonBuffer.createObject();
32 | void setup() {
33 |
34 | root["sensor"] = "gps";
35 | root["time"] = 1351824120;
36 | JsonArray& data = root.createNestedArray("data");
37 | data.add(double_with_n_digits(48.756080, 6));
38 | data.add(double_with_n_digits(2.302038, 6));
39 | root.printTo(JSON);
40 | Serial.begin(115200);
41 | delay(10);
42 |
43 | // We start by connecting to a WiFi network
44 |
45 | Serial.println();
46 | Serial.println();
47 | Serial.print("Connecting to ");
48 | Serial.println(ssid);
49 |
50 | WiFi.begin(ssid, password);
51 |
52 | while (WiFi.status() != WL_CONNECTED) {
53 | delay(500);
54 | Serial.print(".");
55 | }
56 |
57 | Serial.println("");
58 | Serial.println("WiFi connected");
59 | Serial.println("IP address: ");
60 | Serial.println(WiFi.localIP());
61 |
62 | if (!client.connect(host, port)) {
63 | Serial.println("connection failed");
64 | return;
65 | }
66 | if (client.connected())
67 | {
68 | client.send("connection", "message", "Connected !!!!");
69 | }
70 | }
71 |
72 | void loop() {
73 | unsigned long currentMillis = millis();
74 | if (currentMillis - previousMillis > interval)
75 | {
76 | previousMillis = currentMillis;
77 | //client.heartbeat(0);
78 |
79 |
80 |
81 |
82 | Serial.println(JSON);
83 | client.send("atime", "message", "Time please?");
84 | client.sendJSON("JSON", JSON);
85 |
86 | lastsend = millis();
87 | }
88 | if (client.monitor())
89 | {
90 | lastreply = millis();
91 | Serial.println(RID);
92 | if (RID == "atime" && Rname == "time")
93 | {
94 | Serial.print("Il est ");
95 | Serial.println(Rcontent);
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/SocketIOClient.h:
--------------------------------------------------------------------------------
1 | /*
2 | socket.io-arduino-client: a Socket.IO client for the Arduino
3 | Based on the Kevin Rohling WebSocketClient & Bill Roy Socket.io Lbrary
4 | Copyright 2015 Florent Vidal
5 | Permission is hereby granted, free of charge, to any person
6 | obtaining a copy of this software and associated documentation
7 | files (the "Software"), to deal in the Software without
8 | restriction, including without limitation the rights to use,
9 | copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the
11 | Software is furnished to do so, subject to the following
12 | conditions:
13 | JSON support added using https://github.com/bblanchon/ArduinoJson
14 | The above copyright notice and this permission notice shall be
15 | included in all copies or substantial portions of the Software.
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | OTHER DEALINGS IN THE SOFTWARE.
24 | */
25 | #include "Arduino.h"
26 |
27 | #if defined(W5100)
28 | #include
29 | #include "SPI.h" //For W5100
30 | #elif defined(ENC28J60)
31 | #include
32 | #include "SPI.h" //For ENC28J60
33 | #elif defined(ESP8266)
34 | #include //For ESP8266
35 | #elif defined(ESP32)
36 | #include //For ESP32
37 | #elif (!defined(ESP32) && !defined(ESP8266) && !defined(W5100) && !defined(ENC28J60)) //If no interface is defined
38 | #error "Please specify an interface such as W5100, ENC28J60, ESP8266 or ESP32"
39 | #error "above your includes like so : #define ESP8266 "
40 | #endif
41 |
42 | // Length of static data buffers
43 | #define DATA_BUFFER_LEN 120
44 | #define SID_LEN 24
45 |
46 | class SocketIOClient {
47 | public:
48 | bool connect(char hostname[], int port = 80, char query[] = "");
49 | bool connectHTTP(char hostname[], int port = 80);
50 | bool connected();
51 | void disconnect();
52 | bool reconnect(char hostname[], int port = 80, char query[] = "");
53 | bool monitor();
54 | void sendMessage(String message = "");
55 | void send(String RID, String Rname, String Rcontent);
56 | void sendNSP();
57 | void sendJSON(String RID, String JSON);
58 | void heartbeat(int select);
59 | void clear();
60 | void getREST(String path);
61 | void postREST(String path, String type, String data);
62 | void putREST(String path, String type, String data);
63 | void deleteREST(String path);
64 | private:
65 | void parser(int index);
66 | void sendHandshake(char hostname[], char query[] = "");
67 | #if defined(W5100) || defined(ENC28J60)
68 | EthernetClient client; //For ENC28J60 or W5100
69 | #endif
70 | #if defined(ESP8266) || defined(ESP32)
71 | WiFiClient client; //For ESP8266 or ESP32
72 | #endif
73 |
74 | bool readHandshake();
75 | void readLine();
76 | char *dataptr;
77 | char databuffer[DATA_BUFFER_LEN];
78 | char sid[SID_LEN];
79 | char key[28];
80 | char *hostname;
81 | char *query;
82 | char *nsp;
83 | int port;
84 |
85 | void findColon(char which);
86 | void terminateCommand(void);
87 | bool waitForInput(void);
88 | void eatHeader(void);
89 | };
90 |
--------------------------------------------------------------------------------
/examples/Hello_time_sparkfun.ino:
--------------------------------------------------------------------------------
1 | /* DISCLAIMER : IT MAY NOT WORK...
2 | * This sketch sends data via HTTP GET requests to data.sparkfun.com service.
3 | *
4 | * You need to get streamId and privateKey at data.sparkfun.com and paste them
5 | * below. Or just customize this script to talk to other HTTP servers.
6 | *
7 | */
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 |
15 | StaticJsonBuffer<200> jsonBuffer;
16 | int connectedWF = 0;
17 |
18 | byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
19 | char server[] = "firma-transport.ro";
20 |
21 | SocketIOClient client;
22 | const char* ssid = "SSID";
23 | const char* password = "WPA KEY";
24 |
25 | char host[] = "192.168.0.5";
26 | int port = 1234;
27 | extern String RID;
28 | extern String Rname;
29 | extern String Rcontent;
30 |
31 | unsigned long previousMillis = 0;
32 | long interval = 5000;
33 | unsigned long lastreply = 0;
34 | unsigned long lastsend = 0;
35 | String JSON;
36 | JsonObject& root = jsonBuffer.createObject();
37 | void setup() {
38 |
39 | if (esp8266.begin()) {
40 | Serial.println("ESP8266 ready to go!");
41 | connectToWifi();
42 | }
43 | else {
44 | Serial.println("Unable to communicate with the ESP8266 :(");
45 |
46 |
47 | delay(2000);
48 |
49 | root["sensor"] = "gps";
50 | root["time"] = 1351824120;
51 | JsonArray& data = root.createNestedArray("data");
52 | data.add(double_with_n_digits(48.756080, 6));
53 | data.add(double_with_n_digits(2.302038, 6));
54 | root.printTo(JSON);
55 | Serial.begin(115200);
56 | delay(10);
57 |
58 | // We start by connecting to a WiFi network
59 |
60 | Serial.println();
61 | Serial.println();
62 | Serial.print("Connecting to ");
63 | Serial.println(ssid);
64 |
65 | WiFi.begin(ssid, password);
66 |
67 | while (WiFi.status() != WL_CONNECTED) {
68 | delay(500);
69 | Serial.print(".");
70 | }
71 |
72 | Serial.println("");
73 | Serial.println("WiFi connected");
74 | Serial.println("IP address: ");
75 | Serial.println(WiFi.localIP());
76 |
77 | if (!client.connect(host, port)) {
78 | Serial.println("connection failed");
79 | return;
80 | }
81 | if (client.connected())
82 | {
83 | client.send("connection", "message", "Connected !!!!");
84 | }
85 | }
86 |
87 | void connectToWifi() {
88 | int retVal;
89 | retVal = esp8266.connect("ssid", "pass");
90 | if (retVal < 0)
91 | {
92 | Serial.println("Not connected");
93 | }
94 | else {
95 | IPAddress myIP = esp8266.localIP();
96 | Serial.println("Connected to internet OK");
97 | connectedWF = 1;
98 | }
99 | }
100 |
101 |
102 |
103 |
104 | void loop() {
105 | if ( connectedWF == 0 ) {
106 | connectToWifi();
107 | }
108 | unsigned long currentMillis = millis();
109 | if (currentMillis - previousMillis > interval)
110 | {
111 | previousMillis = currentMillis;
112 | //client.heartbeat(0);
113 |
114 |
115 |
116 |
117 | Serial.println(JSON);
118 | client.send("atime", "message", "Time please?");
119 | client.sendJSON("JSON", JSON);
120 |
121 | lastsend = millis();
122 | }
123 | if (client.monitor())
124 | {
125 | lastreply = millis();
126 | Serial.println(RID);
127 | if (RID == "atime" && Rname == "time")
128 | {
129 | Serial.print("Il est ");
130 | Serial.println(Rcontent);
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Socket.io Library for v1.x and v2.x
2 | Socket.io Library for Arduino
3 | ## Navgation
4 | - [News](#news)
5 | - [Download](#download)
6 | - [Contributors](#contributors)
7 | - [Examples](#examples)
8 | - [W5100](#example-w5100)
9 | - [ESP8266](#example-ESP8266)
10 | - [ESP32](#example-ESP32)
11 |
12 | ---
13 | ## News
14 | 1. Works with W5100 & ENC28J60 as well as ESP8266 and ESP32 (beta)
15 | 2. Library will not work when the ESP8266 is being driven by a Uno.
16 | 3. Support for JSON was added using [this library](https://github.com/bblanchon/ArduinoJson).
17 | 4. Instead of using client.send, you can now use client.sendJSON
18 | 5. Thanks to @funkyguy4000, users can now use #define ESP8266, #define W5100 or #define ENC28J60
19 | no need to edit socketio.h anymore
20 | 6. headers are not yet handled, soon
21 | 7. incoming messages can now be longer than 125 bytes (at least up to 255 bytes)
22 |
23 | ---
24 | ## Download Releases
25 | Download in releases and include zip file in arduino ide.
26 | [Release 1.0](/releases/tag/1.0)
27 | ---
28 |
29 | REST API added: ```getREST(path)```, ```postREST(path, type, data)```, ```putREST(path, type, data)```, ```deleteREST(path)```
30 |
31 | ---
32 | ## Examples
33 |
34 | ### W5100
35 |
36 | ```
37 | #define W5100
38 | #include
39 |
40 | SocketIOClient client;
41 | byte mac[] = { 0xAA, 0x00, 0xBE, 0xEF, 0xFE, 0xEE };
42 | char hostname[] = "192.168.0.5";
43 | int port = 1234;
44 |
45 | extern String RID;
46 | extern String Rname;
47 | extern String Rcontent;
48 |
49 | unsigned long previousMillis = 0;
50 | long interval = 10000;
51 | void setup() {
52 | pinMode(10, OUTPUT); //for some ethernet shield on the mega : disables the SD and enables the W5100
53 | digitalWrite(10, LOW);
54 | pinMode(4, OUTPUT);
55 | digitalWrite(4, HIGH);
56 | Serial.begin(9600);
57 |
58 | Ethernet.begin(mac);
59 |
60 | if (!client.connect(hostname, port))
61 | Serial.println(F("Not connected."));
62 |
63 | if (client.connected()){
64 | client.send("connection", "message", "Connected !!!!");
65 | }else{
66 | Serial.println("Connection Error");
67 | while(1);
68 | }
69 | delay(1000);
70 | }
71 |
72 | void loop()
73 | {
74 | unsigned long currentMillis = millis();
75 | if(currentMillis - previousMillis > interval)
76 | {
77 | previousMillis = currentMillis;
78 | //client.heartbeat(0);
79 | client.send("atime", "message", "Time please?");
80 | }
81 | if (client.monitor())
82 | {
83 | Serial.println(RID);
84 | if (RID == "atime" && Rname == "time")
85 | {
86 | Serial.print("Time is ");
87 | Serial.println(Rcontent);
88 | }
89 | }
90 | }
91 | ```
92 | ### ESP8266
93 |
94 | ```
95 | #define ESP8266
96 | #include
97 |
98 | SocketIOClient client;
99 | const char* ssid = "SSID";
100 | const char* password = "WPA KEY";
101 |
102 | char host[] = "192.168.0.5";
103 | int port = 1234;
104 | extern String RID;
105 | extern String Rname;
106 | extern String Rcontent;
107 |
108 | unsigned long previousMillis = 0;
109 | long interval = 5000;
110 | unsigned long lastreply = 0;
111 | unsigned long lastsend = 0;
112 | String JSON;
113 | JsonObject& root = jsonBuffer.createObject();
114 | void setup() {
115 |
116 | root["sensor"] = "gps";
117 | root["time"] = 1351824120;
118 | JsonArray& data = root.createNestedArray("data");
119 | data.add(double_with_n_digits(48.756080, 6));
120 | data.add(double_with_n_digits(2.302038, 6));
121 | root.printTo(JSON);
122 | Serial.begin(115200);
123 | delay(10);
124 |
125 | // We start by connecting to a WiFi network
126 |
127 | Serial.println();
128 | Serial.println();
129 | Serial.print("Connecting to ");
130 | Serial.println(ssid);
131 |
132 | WiFi.begin(ssid, password);
133 |
134 | while (WiFi.status() != WL_CONNECTED) {
135 | delay(500);
136 | Serial.print(".");
137 | }
138 |
139 | Serial.println("");
140 | Serial.println("WiFi connected");
141 | Serial.println("IP address: ");
142 | Serial.println(WiFi.localIP());
143 |
144 | if (!client.connect(host, port)) {
145 | Serial.println("connection failed");
146 | return;
147 | }
148 | if (client.connected()){
149 | client.send("connection", "message", "Connected !!!!");
150 | }
151 | }
152 |
153 | void loop() {
154 | unsigned long currentMillis = millis();
155 | if (currentMillis - previousMillis > interval)
156 | {
157 | previousMillis = currentMillis;
158 | //client.heartbeat(0);
159 | Serial.println(JSON);
160 | client.send("atime", "message", "Time please?");
161 | client.sendJSON("JSON", JSON);
162 |
163 | lastsend = millis();
164 | }
165 | if (client.monitor())
166 | {
167 | lastreply = millis();
168 | Serial.println(RID);
169 | if (RID == "atime" && Rname == "time")
170 | {
171 | Serial.print("Il est ");
172 | Serial.println(Rcontent);
173 | }
174 | }
175 | }
176 | ```
177 | ### ESP32
178 |
179 | ```
180 | #define ESP32
181 | #include
182 |
183 | SocketIOClient client;
184 | const char* ssid = "xxxxxxxxxxxxxxxxx";
185 | const char* password = "xxxxxxxxxxxxx";
186 |
187 | char host[] = "192.168.1.1";
188 | int port = 1234;
189 | extern String RID;
190 | extern String Rname;
191 | extern String Rcontent;
192 |
193 | unsigned long previousMillis = 0;
194 | long interval = 5000;
195 | unsigned long lastreply = 0;
196 | unsigned long lastsend = 0;
197 |
198 | void setup() {
199 | Serial.begin(115200);
200 | delay(10);
201 |
202 | // We start by connecting to a WiFi network
203 |
204 | Serial.println();
205 | Serial.println();
206 | Serial.print("Connecting to ");
207 | Serial.println(ssid);
208 |
209 | WiFi.begin(ssid, password);
210 |
211 | while (WiFi.status() != WL_CONNECTED) {
212 | delay(500);
213 | Serial.print(".");
214 | }
215 |
216 | Serial.println("");
217 | Serial.println("WiFi connected");
218 | Serial.println("IP address: ");
219 | Serial.println(WiFi.localIP());
220 |
221 | if (!client.connect(host, port)) {
222 | Serial.println("connection failed");
223 | return;
224 | }
225 | if (client.connected()){
226 | client.send("connection", "message", "Connected !!!!");
227 | }
228 | }
229 |
230 | void loop() {
231 | unsigned long currentMillis = millis();
232 | if (currentMillis - previousMillis > interval)
233 | {
234 | previousMillis = currentMillis;
235 | //client.heartbeat(0);
236 | Serial.print("************************************** ");
237 | Serial.println(lastsend);
238 | client.send("atime", "message", "Time please?");
239 | lastsend = millis();
240 | Serial.print("************************************** ");
241 | Serial.println(lastsend);
242 | }
243 | if (client.monitor())
244 | {
245 | lastreply = millis();
246 | Serial.println(RID);
247 | if (RID == "atime" && Rname == "time")
248 | {
249 | Serial.print("Il est ");
250 | Serial.println(Rcontent);
251 | }
252 | }
253 | }
254 | ```
255 | ---
256 |
257 |
258 |
259 | ## Contributors
260 |
261 | 1. [washo4evr](https://github.com/washo4evr)
262 | 1. [all-lala](https://github.com/al-lala)
263 | 1. [andreghisleni](https://github.com/andreghisleni/)
264 |
--------------------------------------------------------------------------------
/SocketIOClient.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | socket.io-arduino-client: a Socket.IO client for the Arduino
3 | Based on the Kevin Rohling WebSocketClient & Bill Roy Socket.io Lbrary
4 | Copyright 2015 Florent Vidal
5 | Supports Socket.io v1.x
6 | Permission is hereby granted, free of charge, to any person
7 | obtaining a copy of this software and associated documentation
8 | files (the "Software"), to deal in the Software without
9 | restriction, including without limitation the rights to use,
10 | copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the
12 | Software is furnished to do so, subject to the following
13 | conditions:
14 | The above copyright notice and this permission notice shall be
15 | included in all copies or substantial portions of the Software.
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 | OTHER DEALINGS IN THE SOFTWARE.
24 | */
25 | #define ESP32
26 | #include
27 |
28 |
29 | String tmpdata = ""; //External variables
30 | String RID = "";
31 | String Rname = "";
32 | String Rcontent = "";
33 |
34 |
35 |
36 | bool SocketIOClient::connect(char thehostname[], int theport, char thequery[] = "") {
37 | if (!client.connect(thehostname, theport)) return false;
38 | hostname = thehostname;
39 | port = theport;
40 | query = thequery;
41 | sendHandshake(hostname, query);
42 | return readHandshake();
43 | }
44 |
45 | bool SocketIOClient::connectHTTP(char thehostname[], int theport) {
46 | if (!client.connect(thehostname, theport)) return false;
47 | hostname = thehostname;
48 | port = theport;
49 | return true;
50 | }
51 |
52 | bool SocketIOClient::reconnect(char thehostname[], int theport, char thequery[] = "")
53 | {
54 | if (!client.connect(thehostname, theport)) return false;
55 | hostname = thehostname;
56 | port = theport;
57 | query = thequery;
58 | sendHandshake(hostname, query);
59 | return readHandshake();
60 | }
61 |
62 | bool SocketIOClient::connected() {
63 | return client.connected();
64 | }
65 |
66 | void SocketIOClient::disconnect() {
67 | client.stop();
68 | }
69 |
70 | // find the nth colon starting from dataptr
71 | void SocketIOClient::findColon(char which) {
72 | while (*dataptr) {
73 | if (*dataptr == ':') {
74 | if (--which <= 0) return;
75 | }
76 | ++dataptr;
77 | }
78 | }
79 |
80 | // terminate command at dataptr at closing double quote
81 | void SocketIOClient::terminateCommand(void) {
82 | dataptr[strlen(dataptr) - 3] = 0;
83 | }
84 |
85 | void SocketIOClient::parser(int index) {
86 | String rcvdmsg = "";
87 | int sizemsg = databuffer[index + 1]; // 0-125 byte, index ok Fix provide by Galilei11. Thanks
88 | if (databuffer[index + 1]>125)
89 | {
90 | sizemsg = databuffer[index + 2]; // 126-255 byte
91 | index += 1; // index correction to start
92 | }
93 | Serial.print("Message size = "); //Can be used for debugging
94 | Serial.println(sizemsg); //Can be used for debugging
95 | for (int i = index + 2; i < index + sizemsg + 2; i++)
96 | rcvdmsg += (char)databuffer[i];
97 | Serial.print("Received message = "); //Can be used for debugging
98 | Serial.println(rcvdmsg); //Can be used for debugging
99 | switch (rcvdmsg[0])
100 | {
101 | case '2':
102 | Serial.println("Ping received - Sending Pong");
103 | heartbeat(1);
104 | break;
105 |
106 | case '3':
107 | Serial.println("Pong received - All good");
108 | break;
109 |
110 | case '4':
111 | switch (rcvdmsg[1])
112 | {
113 | case '0':
114 | Serial.println("Upgrade to WebSocket confirmed");
115 | break;
116 | case '2':
117 | int end = rcvdmsg.indexOf("\",");
118 | if (end == -1) {
119 | end = rcvdmsg.indexOf("\"]");
120 | }
121 | RID = rcvdmsg.substring(rcvdmsg.indexOf("[\"")+2, end);
122 | RID = rcvdmsg.substring(4, rcvdmsg.indexOf("\","));
123 | Rname = rcvdmsg.substring(rcvdmsg.indexOf("\",") + 4, rcvdmsg.indexOf("\":"));
124 | Rcontent = rcvdmsg.substring(rcvdmsg.indexOf("\":") + 3, rcvdmsg.indexOf("\"}"));
125 | //Serial.println("RID = " + RID);
126 | //Serial.println("Rname = " + Rname);
127 | //Serial.println("Rcontent = " + Rcontent);
128 | Serial.println(rcvdmsg);
129 | break;
130 | }
131 | }
132 | }
133 |
134 | bool SocketIOClient::monitor() {
135 | int index = -1;
136 | int index2 = -1;
137 | String tmp = "";
138 | *databuffer = 0;
139 |
140 | //Checking for client availability, If not returning false
141 | if (!client.connected() &&
142 | !client.connect(hostname, port) &&
143 | !client.available()) {
144 | return false;
145 | }
146 |
147 | while (client.available()) {
148 | readLine();
149 | tmp = databuffer;
150 | Serial.println(databuffer);
151 | dataptr = databuffer;
152 | index = tmp.indexOf((char)129); //129 DEC = 0x81 HEX = sent for proper communication
153 | index2 = tmp.indexOf((char)129, index + 1);
154 | /*Serial.print("Index = "); //Can be used for debugging
155 | Serial.print(index);
156 | Serial.print(" & Index2 = ");
157 | Serial.println(index2);*/
158 | if (index != -1)
159 | {
160 | parser(index);
161 | }
162 | if (index2 != -1)
163 | {
164 | parser(index2);
165 | }
166 | }
167 | return true;
168 | }
169 |
170 | void SocketIOClient::sendHandshake(char hostname[], char query[] = "") {
171 | client.print(F("GET /socket.io/1/?"));
172 | client.print(query);
173 | client.println(F("&transport=polling&b64=true HTTP/1.1"));
174 | client.print(F("Host: "));
175 | client.println(hostname);
176 | client.println(F("Origin: Arduino\r\n"));
177 | }
178 |
179 | bool SocketIOClient::waitForInput(void) {
180 | unsigned long now = millis();
181 | while (!client.available() && ((millis() - now) < 30000UL)) { ; }
182 | return client.available();
183 | }
184 |
185 | void SocketIOClient::eatHeader(void) {
186 | while (client.available()) { // consume the header
187 | readLine();
188 | if (strlen(databuffer) == 0) break;
189 | }
190 | }
191 |
192 | bool SocketIOClient::readHandshake() {
193 |
194 | if (!waitForInput()) return false;
195 |
196 | // check for happy "HTTP/1.1 200" response
197 | readLine();
198 | if (atoi(&databuffer[9]) != 200) {
199 | while (client.available()) readLine();
200 | client.stop();
201 | return false;
202 | }
203 | eatHeader();
204 | readLine();
205 | String tmp = databuffer;
206 |
207 | int sidindex = tmp.indexOf("sid");
208 | int sidendindex = tmp.indexOf("\"", sidindex + 6);
209 | int count = sidendindex - sidindex - 6;
210 |
211 | for (int i = 0; i < count; i++)
212 | {
213 | sid[i] = databuffer[i + sidindex + 6];
214 | }
215 | Serial.println(" ");
216 | Serial.print(F("Connected. SID="));
217 | Serial.println(sid); // sid:transport:timeout
218 |
219 | while (client.available()) readLine();
220 | client.stop();
221 | delay(1000);
222 |
223 | // reconnect on websocket connection
224 | if (!client.connect(hostname, port)) {
225 | Serial.print(F("Websocket failed."));
226 | return false;
227 | }
228 | Serial.println(F("Connecting via Websocket"));
229 |
230 | client.print(F("GET /socket.io/1/websocket/?"));
231 | client.print(query);
232 | client.print(F("&transport=websocket&b64=true&sid="));
233 | client.print(sid);
234 | client.print(F(" HTTP/1.1\r\n"));
235 |
236 | client.print(F("Host: "));
237 | client.print(hostname);
238 | client.print("\r\n");
239 | client.print(F("Sec-WebSocket-Version: 13\r\n"));
240 | client.print(F("Origin: ArduinoSocketIOClient\r\n"));
241 | client.print(F("Sec-WebSocket-Extensions: permessage-deflate\r\n"));
242 | client.print(F("Sec-WebSocket-Key: IAMVERYEXCITEDESP32FTW==\r\n")); // can be anything
243 |
244 | client.print(F("Cookie: io="));
245 | client.print(sid);
246 | client.print("\r\n");
247 |
248 | client.print(F("Connection: Upgrade\r\n"));
249 |
250 | client.println(F("Upgrade: websocket\r\n")); // socket.io v2.0.3 supported
251 |
252 |
253 |
254 |
255 | if (!waitForInput()) return false;
256 | readLine();
257 | if (atoi(&databuffer[9]) != 101) { // check for "HTTP/1.1 101 response, means Updrage to Websocket OK
258 | while (client.available()) readLine();
259 | client.stop();
260 | return false;
261 | }
262 | readLine();
263 | readLine();
264 | readLine();
265 | for (int i = 0; i < 28; i++)
266 | {
267 | key[i] = databuffer[i + 22]; //key contains the Sec-WebSocket-Accept, could be used for verification
268 | }
269 |
270 |
271 | eatHeader();
272 |
273 |
274 | /*
275 | Generating a 32 bits mask requiered for newer version
276 | Client has to send "52" for the upgrade to websocket
277 | */
278 | randomSeed(analogRead(0));
279 | String mask = "";
280 | String masked = "52";
281 | String message = "52";
282 | for (int i = 0; i < 4; i++) //generate a random mask, 4 bytes, ASCII 0 to 9
283 | {
284 | char a = random(48, 57);
285 | mask += a;
286 | }
287 |
288 | for (int i = 0; i < message.length(); i++)
289 | masked[i] = message[i] ^ mask[i % 4]; //apply the "mask" to the message ("52")
290 |
291 |
292 |
293 | client.print((char)0x81); //has to be sent for proper communication
294 | client.print((char)130); //size of the message (2) + 128 because message has to be masked
295 | client.print(mask);
296 | client.print(masked);
297 |
298 | monitor(); // treat the response as input
299 | return true;
300 | }
301 |
302 | void SocketIOClient::getREST(String path)
303 | {
304 | String message = "GET /" + path + "/ HTTP/1.1";
305 | client.println(message);
306 | client.print(F("Host: "));
307 | client.println(hostname);
308 | client.println(F("Origin: Arduino"));
309 | client.println(F("Connection: close\r\n"));
310 | }
311 |
312 | void SocketIOClient::postREST(String path, String type, String data)
313 | {
314 | String message = "POST /" + path + "/ HTTP/1.1";
315 | client.println(message);
316 | client.print(F("Host: "));
317 | client.println(hostname);
318 | client.println(F("Origin: Arduino"));
319 | client.println(F("Connection: close\r\n"));
320 | client.print(F("Content-Length: "));
321 | client.println(data.length());
322 | client.print(F("Content-Type: "));
323 | client.println(type);
324 | client.println("\r\n");
325 | client.println(data);
326 |
327 | }
328 |
329 | void SocketIOClient::putREST(String path, String type, String data)
330 | {
331 | String message = "PUT /" + path + "/ HTTP/1.1";
332 | client.println(message);
333 | client.print(F("Host: "));
334 | client.println(hostname);
335 | client.println(F("Origin: Arduino"));
336 | client.println(F("Connection: close\r\n"));
337 | client.print(F("Content-Length: "));
338 | client.println(data.length());
339 | client.print(F("Content-Type: "));
340 | client.println(type);
341 | client.println("\r\n");
342 | client.println(data);
343 | }
344 |
345 | void SocketIOClient::deleteREST(String path)
346 | {
347 | String message = "DELETE /" + path + "/ HTTP/1.1";
348 | client.println(message);
349 | client.print(F("Host: "));
350 | client.println(hostname);
351 | client.println(F("Origin: Arduino"));
352 | client.println(F("Connection: close\r\n"));
353 | }
354 |
355 | void SocketIOClient::readLine() {
356 | for (int i = 0; i < DATA_BUFFER_LEN; i++)
357 | databuffer[i] = ' ';
358 | dataptr = databuffer;
359 | while (client.available() && (dataptr < &databuffer[DATA_BUFFER_LEN - 2]))
360 | {
361 | char c = client.read();
362 | Serial.print(c); //Can be used for debugging
363 | if (c == 0) Serial.print("");
364 | else if (c == 255) Serial.println("");
365 | else if (c == '\r') { ; }
366 | else if (c == '\n') break;
367 | else *dataptr++ = c;
368 | }
369 | *dataptr = 0;
370 | }
371 |
372 | void SocketIOClient::send(String RID, String Rname, String Rcontent) {
373 |
374 | String message = "42[\"" + RID + "\",{\"" + Rname + "\":\"" + Rcontent + "\"}]";
375 | int header[10];
376 | header[0] = 0x81;
377 | int msglength = message.length();
378 | randomSeed(analogRead(0));
379 | String mask = "";
380 | String masked = message;
381 | for (int i = 0; i < 4; i++)
382 | {
383 | char a = random(48, 57);
384 | mask += a;
385 | }
386 | for (int i = 0; i < msglength; i++)
387 | masked[i] = message[i] ^ mask[i % 4];
388 |
389 | client.print((char)header[0]); //has to be sent for proper communication
390 | //Depending on the size of the message
391 | if (msglength <= 125)
392 | {
393 | header[1] = msglength + 128;
394 | client.print((char)header[1]); //size of the message + 128 because message has to be masked
395 | }
396 | else if (msglength >= 126 && msglength <= 65535)
397 | {
398 | header[1] = 126 + 128;
399 | client.print((char)header[1]);
400 | header[2] = (msglength >> 8) & 255;
401 | client.print((char)header[2]);
402 | header[3] = (msglength)& 255;
403 | client.print((char)header[3]);
404 | }
405 | else
406 | {
407 | header[1] = 127 + 128;
408 | client.print((char)header[1]);
409 | header[2] = (msglength >> 56) & 255;
410 | client.print((char)header[2]);
411 | header[3] = (msglength >> 48) & 255;
412 | client.print((char)header[4]);
413 | header[4] = (msglength >> 40) & 255;
414 | client.print((char)header[4]);
415 | header[5] = (msglength >> 32) & 255;
416 | client.print((char)header[5]);
417 | header[6] = (msglength >> 24) & 255;
418 | client.print((char)header[6]);
419 | header[7] = (msglength >> 16) & 255;
420 | client.print((char)header[7]);
421 | header[8] = (msglength >> 8) & 255;
422 | client.print((char)header[8]);
423 | header[9] = (msglength)& 255;
424 | client.print((char)header[9]);
425 | }
426 |
427 | client.print(mask);
428 | client.print(masked);
429 | }
430 |
431 | void SocketIOClient::sendJSON(String RID, String JSON) {
432 | String message = "42[\"" + RID + "\"," + JSON + "]";
433 | int header[10];
434 | header[0] = 0x81;
435 | int msglength = message.length();
436 | randomSeed(analogRead(0));
437 | String mask = "";
438 | String masked = message;
439 | for (int i = 0; i < 4; i++)
440 | {
441 | char a = random(48, 57);
442 | mask += a;
443 | }
444 | for (int i = 0; i < msglength; i++)
445 | masked[i] = message[i] ^ mask[i % 4];
446 |
447 | client.print((char)header[0]); //has to be sent for proper communication
448 | //Depending on the size of the message
449 | if (msglength <= 125)
450 | {
451 | header[1] = msglength + 128;
452 | client.print((char)header[1]); //size of the message + 128 because message has to be masked
453 | }
454 | else if (msglength >= 126 && msglength <= 65535)
455 | {
456 | header[1] = 126 + 128;
457 | client.print((char)header[1]);
458 | header[2] = (msglength >> 8) & 255;
459 | client.print((char)header[2]);
460 | header[3] = (msglength)& 255;
461 | client.print((char)header[3]);
462 | }
463 | else
464 | {
465 | header[1] = 127 + 128;
466 | client.print((char)header[1]);
467 | header[2] = (msglength >> 56) & 255;
468 | client.print((char)header[2]);
469 | header[3] = (msglength >> 48) & 255;
470 | client.print((char)header[4]);
471 | header[4] = (msglength >> 40) & 255;
472 | client.print((char)header[4]);
473 | header[5] = (msglength >> 32) & 255;
474 | client.print((char)header[5]);
475 | header[6] = (msglength >> 24) & 255;
476 | client.print((char)header[6]);
477 | header[7] = (msglength >> 16) & 255;
478 | client.print((char)header[7]);
479 | header[8] = (msglength >> 8) & 255;
480 | client.print((char)header[8]);
481 | header[9] = (msglength)& 255;
482 | client.print((char)header[9]);
483 | }
484 |
485 | client.print(mask);
486 | client.print(masked);
487 | }
488 |
489 | void SocketIOClient::heartbeat(int select) {
490 | randomSeed(analogRead(0));
491 | String mask = "";
492 | String masked = "";
493 | String message = "";
494 | if (select == 0)
495 | {
496 | masked = "2";
497 | message = "2";
498 | }
499 | else
500 | {
501 | masked = "3";
502 | message = "3";
503 | }
504 | for (int i = 0; i < 4; i++) //generate a random mask, 4 bytes, ASCII 0 to 9
505 | {
506 | char a = random(48, 57);
507 | mask += a;
508 | }
509 |
510 | for (int i = 0; i < message.length(); i++)
511 | masked[i] = message[i] ^ mask[i % 4]; //apply the "mask" to the message ("2" : ping or "3" : pong)
512 |
513 |
514 |
515 | client.print((char)0x81); //has to be sent for proper communication
516 | client.print((char)129); //size of the message (1) + 128 because message has to be masked
517 | client.print(mask);
518 | client.print(masked);
519 | }
520 |
--------------------------------------------------------------------------------