├── 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 | --------------------------------------------------------------------------------