ESP3D  3.0
Firmware for ESP boards connected to 3D Printer
websocket_server.cpp
Go to the documentation of this file.
1 /*
2  websocket_server.cpp - websocket functions class
3 
4  Copyright (c) 2014 Luc Lebosse. All rights reserved.
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public
8  License as published by the Free Software Foundation; either
9  version 2.1 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public
17  License along with this library; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 
21 
22 #include "../../include/esp3d_config.h"
23 
24 #if defined (HTTP_FEATURE) || defined(WS_DATA_FEATURE)
25 
26 
27 #include "websocket_server.h"
28 #include <WebSocketsServer.h>
29 #include "../../core/settings_esp3d.h"
30 #include "../../core/esp3doutput.h"
31 #include "../../core/commands.h"
32 
34 #if defined(WS_DATA_FEATURE)
36 #endif //WS_DATA_FEATURE
37 void WebSocket_Server::pushMSG (const char * data)
38 {
39  _websocket_server->broadcastTXT(data);
40 }
41 
42 void WebSocket_Server::pushMSG (uint num, const char * data)
43 {
44  if (_websocket_server) {
45  _websocket_server->sendTXT(num, data);
46  }
47 }
48 
50 {
51  if (_websocket_server) {
52  _websocket_server->disconnect();
53  }
54 }
55 #if defined(WS_DATA_FEATURE)
56 //Events for Websocket bridge
57 void handle_Websocket_Server_Event(uint8_t num, uint8_t type, uint8_t * payload, size_t length)
58 {
59  (void)num;
60  switch(type) {
61  case WStype_DISCONNECTED:
62  log_esp3d("[%u] Disconnected! port %d", num,websocket_data_server.port());
63  break;
64  case WStype_CONNECTED: {
65  log_esp3d("[%u] Connected! port %d", num,websocket_data_server.port());
66  }
67  break;
68  case WStype_TEXT:
69  log_esp3d("[%u] get Text: %s port %d", num, payload,websocket_data_server.port());
70  websocket_data_server.push2RXbuffer(payload, length);
71  break;
72  case WStype_BIN:
73  log_esp3d("[%u] get binary length: %u port %d", num, length,websocket_data_server.port());
74  websocket_data_server.push2RXbuffer(payload, length);
75  break;
76  default:
77  break;
78  }
79 
80 }
81 #endif //WS_DATA_FEATURE
82 #if defined (HTTP_FEATURE)
83 //Events for Websocket used in WebUI for events and serial bridge
84 void handle_Websocket_Terminal_Event(uint8_t num, uint8_t type, uint8_t * payload, size_t length)
85 {
86  (void)payload;
87  (void)length;
88  switch(type) {
89  case WStype_DISCONNECTED:
90  log_esp3d("[%u] Socket Disconnected port %d!", num,websocket_terminal_server.port());
91  break;
92  case WStype_CONNECTED: {
93  String s = "currentID:" + String(num);
94  // send message to client
96  websocket_terminal_server.pushMSG(num, s.c_str());
97  s = "activeID:" + String(num);
99  log_esp3d("[%u] Socket connected port %d", num,websocket_terminal_server.port());
100  }
101  break;
102  case WStype_TEXT:
103  //we do not expect any input
104  log_esp3d("[IGNORED][%u] get Text: %s port %d", num, payload, websocket_terminal_server.port());
105  break;
106  case WStype_BIN:
107  //we do not expect any input
108  log_esp3d("[IGNORED][%u] get binary length: %u port %d", num, length, websocket_terminal_server.port());
109  break;
110  default:
111  break;
112  }
113 
114 }
115 #endif //HTTP_FEATURE
116 
118 {
119  return _RXbufferSize;
120 }
122 {
123  return TXBUFFERSIZE -_TXbufferSize;
124 }
126 {
127  _websocket_server = nullptr;
128  _started = false;
129  _port = 0;
130  _current_id = 0;
131  _isdebug = false;
132  _RXbuffer = nullptr;
133  _RXbufferSize = 0;
134 
135 }
137 {
138  end();
139 }
140 bool WebSocket_Server::begin(uint16_t port, bool debug)
141 {
142  end();
143  if(port == 0) {
145  } else {
146  _port = port;
148  return true;
149  }
150  }
151  _isdebug = debug;
152  _websocket_server = new WebSocketsServer(_port);
153  if (_websocket_server) {
154  _websocket_server->begin();
155 #if defined (HTTP_FEATURE) //terminal websocket for HTTP
156  if(port == 0) {
157  _websocket_server->onEvent(handle_Websocket_Terminal_Event);
158  }
159 #endif //HTTP_FEATURE
160 #if defined (WS_DATA_FEATURE) //terminal websocket for HTTP
161  if((port != 0) && !_isdebug) {
162  _websocket_server->onEvent(handle_Websocket_Server_Event);
163  _RXbuffer= (uint8_t *)malloc(RXBUFFERSIZE +1);
164  if (!_RXbuffer) {
165  return false;
166  }
167  }
168 #endif //WS_DATA_FEATURE
169  _started = true;
170  } else {
171  end();
172  }
173  return _started;
174 }
175 
177 {
178  _current_id = 0;
179  _TXbufferSize = 0;
180  _isdebug = false;
181  if(_RXbuffer) {
182  free(_RXbuffer);
183  _RXbuffer = nullptr;
184  }
185  _RXbufferSize = 0;
186  if (_websocket_server) {
187  _websocket_server->close();
188  delete _websocket_server;
189  _websocket_server = nullptr;
190  _port = 0;
191  }
192  _started = false;
193 }
194 
195 
196 WebSocket_Server::operator bool() const
197 {
198  return _started;
199 }
200 
201 void WebSocket_Server::set_currentID(uint8_t current_id)
202 {
203  _current_id = current_id;
204 }
206 {
207  return _current_id;
208 }
209 
210 size_t WebSocket_Server::write(uint8_t c)
211 {
212  return write(&c,1);;
213 }
214 
215 size_t WebSocket_Server::write(const uint8_t *buffer, size_t size)
216 {
217  if (_started) {
218  if((buffer == nullptr) ||(!_websocket_server) || (size == 0)) {
219  return 0;
220  }
221  if (_TXbufferSize==0) {
222  _lastTXflush = millis();
223  }
224  //send full line
225  if (_TXbufferSize + size > TXBUFFERSIZE) {
226  flushTXbuffer();
227  }
228  if(_websocket_server->connectedClients() == 0) {
229  return 0;
230  }
231  //need periodic check to force to flush in case of no end
232  for (uint i = 0; i < size; i++) {
233  _TXbuffer[_TXbufferSize] = buffer[i];
234  _TXbufferSize++;
235  }
236  //if(!_isdebug) {
237  // log_esp3d("[SOCKET]buffer size %d",_TXbufferSize);
238  //}
239  return size;
240  }
241  return 0;
242 }
243 
244 void WebSocket_Server::push2RXbuffer(uint8_t * sbuf, size_t len)
245 {
246  if (!_RXbuffer || !_started) {
247  return;
248  }
249  for (size_t i = 0; i < len; i++) {
250  _lastRXflush = millis();
251  //command is defined
252  if (char(sbuf[i]) == '\n') {
253  if (_RXbufferSize < RXBUFFERSIZE) {
254  _RXbuffer[_RXbufferSize] = sbuf[i];
255  _RXbufferSize++;
256  }
257  flushRXbuffer();
258  } else if (isPrintable (char(sbuf[i]) ) || char(sbuf[i]) == '\r') {
259  if (_RXbufferSize < RXBUFFERSIZE) {
260  _RXbuffer[_RXbufferSize] = sbuf[i];
261  _RXbufferSize++;
262  } else {
263  flushRXbuffer();
264  _RXbuffer[_RXbufferSize] = sbuf[i];
265  _RXbufferSize++;
266  }
267  } else { //it is not printable char
268  //clean buffer first
269  if (_RXbufferSize > 0) {
270  flushRXbuffer();
271  }
272  //process char
273  _RXbuffer[_RXbufferSize] = sbuf[i];
274  _RXbufferSize++;
275  flushRXbuffer();
276  }
277  }
278 }
279 
280 void WebSocket_Server::flushRXbuffer()
281 {
282  if (!_RXbuffer || !_started) {
283  _RXbufferSize = 0;
284  return;
285  }
287  _RXbuffer[_RXbufferSize] = 0x0;
288  //dispatch command
289  esp3d_commands.process(_RXbuffer, _RXbufferSize, &output);
290  _lastRXflush = millis();
291  _RXbufferSize = 0;
292 }
293 
294 
296 {
297  Hal::wait(0);
298  if (_started) {
299  if (_TXbufferSize > 0) {
300  if ((_TXbufferSize>=TXBUFFERSIZE) || ((millis()- _lastTXflush) > FLUSHTIMEOUT)) {
301  flushTXbuffer();
302  }
303  }
304  if (_RXbufferSize > 0) {
305  if ((_RXbufferSize>=RXBUFFERSIZE) || ((millis()- _lastRXflush) > FLUSHTIMEOUT)) {
306  flushRXbuffer();
307  }
308  }
309  if (_websocket_server) {
310  _websocket_server->loop();
311  }
312  }
313 }
314 
316 {
317  flushTXbuffer();
318  flushRXbuffer();
319 }
320 
321 void WebSocket_Server::flushTXbuffer(void)
322 {
323  if (_started) {
324  if ((_TXbufferSize > 0) && (_websocket_server->connectedClients() > 0 )) {
325  //if(!_isdebug) {
326  // log_esp3d("[SOCKET]flush data, buffer size %d",_TXbufferSize);
327  //}
328  if (_websocket_server) {
329  _websocket_server->broadcastBIN(_TXbuffer,_TXbufferSize);
330  log_esp3d("WS Broadcast bin port %d", port());
331  }
332  //refresh timout
333  _lastTXflush = millis();
334 
335  }
336  }
337  //reset buffer
338  _TXbufferSize = 0;
339 }
340 
341 
342 
343 #endif // HTTP_FEATURE || WS_DATA_FEATURE
344 
esp3d_commands
Commands esp3d_commands
Definition: commands.cpp:26
WebSocket_Server::set_currentID
void set_currentID(uint8_t current_id)
Definition: websocket_server.cpp:201
ESP_HTTP_PORT
#define ESP_HTTP_PORT
Definition: settings_esp3d.h:52
WebSocket_Server
Definition: websocket_server.h:30
Hal::wait
static void wait(uint32_t milliseconds)
Definition: hal.cpp:226
WebSocket_Server::write
size_t write(uint8_t c)
Definition: websocket_server.cpp:210
handle_Websocket_Terminal_Event
void handle_Websocket_Terminal_Event(uint8_t num, uint8_t type, uint8_t *payload, size_t length)
Definition: websocket_server.cpp:84
WebSocket_Server::get_currentID
uint8_t get_currentID()
Definition: websocket_server.cpp:205
WebSocket_Server::available
int available()
Definition: websocket_server.cpp:117
Commands::process
void process(uint8_t *sbuf, size_t len, ESP3DOutput *output, level_authenticate_type auth=LEVEL_GUEST, ESP3DOutput *outputonly=nullptr)
Definition: commands.cpp:36
WebSocket_Server::~WebSocket_Server
~WebSocket_Server()
Definition: websocket_server.cpp:136
websocket_terminal_server
WebSocket_Server websocket_terminal_server
Definition: websocket_server.cpp:33
websocket_data_server
WebSocket_Server websocket_data_server
Definition: websocket_server.cpp:35
handle_Websocket_Server_Event
void handle_Websocket_Server_Event(uint8_t num, uint8_t type, uint8_t *payload, size_t length)
Definition: websocket_server.cpp:57
TXBUFFERSIZE
#define TXBUFFERSIZE
Definition: websocket_server.h:26
websocket_server.h
WebSocket_Server::closeClients
void closeClients()
Definition: websocket_server.cpp:49
WebSocket_Server::pushMSG
void pushMSG(const char *data)
Definition: websocket_server.cpp:37
ESP_WEBSOCKET_CLIENT
#define ESP_WEBSOCKET_CLIENT
Definition: esp3doutput.h:29
WebSocket_Server::end
void end()
Definition: websocket_server.cpp:176
WebSocket_Server::WebSocket_Server
WebSocket_Server()
Definition: websocket_server.cpp:125
WebSocket_Server::availableForWrite
uint availableForWrite()
Definition: websocket_server.cpp:121
WebSocket_Server::flush
void flush(void)
Definition: websocket_server.cpp:315
log_esp3d
#define log_esp3d(format,...)
Definition: debug_esp3d.h:29
ESP_WEBSOCKET_ON
#define ESP_WEBSOCKET_ON
Definition: settings_esp3d.h:67
Settings_ESP3D::read_uint32
static uint32_t read_uint32(int pos, bool *haserror=NULL)
Definition: settings_esp3d.cpp:919
WebSocket_Server::handle
void handle()
Definition: websocket_server.cpp:295
Settings_ESP3D::read_byte
static uint8_t read_byte(int pos, bool *haserror=NULL)
Definition: settings_esp3d.cpp:715
FLUSHTIMEOUT
#define FLUSHTIMEOUT
Definition: websocket_server.h:28
WebSocket_Server::port
uint16_t port()
Definition: websocket_server.h:59
RXBUFFERSIZE
#define RXBUFFERSIZE
Definition: websocket_server.h:27
WebSocket_Server::push2RXbuffer
void push2RXbuffer(uint8_t *sbuf, size_t len)
Definition: websocket_server.cpp:244
ESP3DOutput
Definition: esp3doutput.h:48
WebSocket_Server::begin
bool begin(uint16_t port=0, bool debug=false)
Definition: websocket_server.cpp:140