Skip to content

Commit fe23f0c

Browse files
authored
Grbl grblHAL better support for realtime commands (#1064)
* Add a realtime command detector * Move `\r` as printable char and not replaced as `\n` * Refactorize Serial service code to avoid redondant code between esp32 and esp8266 * Implement isrealtimeCommand check for serial and centralize function in string helper * Add new type message : realtimecmd * Update simulator to handle commands and realtime commands * Add simple serial test tool * Generate error if use HAS_DISPLAY with grbl/grblHAL * Implement isRealTimeCommand for BT client * Simplify BT push2buffer code * Implement support for realtimecommand in telnet * Implement isRealTimeCommand on websocket RX * Simplify push2RXbuffer for websocket * Implement isRealTimeCommand for USB serial * Bump version
1 parent 7b99d8a commit fe23f0c

27 files changed

+765
-586
lines changed

esp3d/configuration.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@
443443
/* Printer screen
444444
* If your printer has a display
445445
*/
446-
#define PRINTER_HAS_DISPLAY
446+
//#define PRINTER_HAS_DISPLAY
447447

448448
/* ESP3D screen
449449
* Screen connected to ESP board
@@ -644,9 +644,9 @@
644644
// LOG_OUTPUT_SERIAL2
645645
// LOG_OUTPUT_TELNET
646646
// LOG_OUTPUT_WEBSOCKET
647-
// #define ESP_LOG_FEATURE LOG_OUTPUT_SERIAL0
647+
#define ESP_LOG_FEATURE LOG_OUTPUT_SERIAL0
648648

649-
// #define ESP3D_DEBUG_LEVEL LOG_LEVEL_DEBUG
649+
#define ESP3D_DEBUG_LEVEL LOG_LEVEL_DEBUG
650650

651651
#ifdef ESP_LOG_FEATURE
652652
#define LOG_ESP3D_BAUDRATE 115200
@@ -657,7 +657,7 @@
657657
// #define ESP_BENCHMARK_FEATURE
658658

659659
// Disable sanity check at compilation
660-
// #define ESP_NO_SANITY_CHECK
660+
#define ESP_NO_SANITY_CHECK
661661

662662
/************************************
663663
*

esp3d/src/core/esp3d.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ void Esp3D::restart_now() {
278278
#if defined(FILESYSTEM_FEATURE)
279279
ESP_FileSystem::end();
280280
#endif // FILESYSTEM_FEATURE
281-
#if COMMUNICATION_PROTOCOL == RAW_SERIAL || COMMUNICATION_PROTOCOL == MKS_SERIAL
281+
#if (COMMUNICATION_PROTOCOL == RAW_SERIAL || COMMUNICATION_PROTOCOL == MKS_SERIAL) & defined(ARDUINO_ARCH_ESP8266)
282282
esp3d_serial_service.swap();
283283
#endif // COMMUNICATION_PROTOCOL == RAW_SERIAL || COMMUNICATION_PROTOCOL ==
284284
// MKS_SERIAL

esp3d/src/core/esp3d_commands.cpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,6 @@ ESP3DCommands::ESP3DCommands() {
107107

108108
ESP3DCommands::~ESP3DCommands() {}
109109

110-
bool ESP3DCommands::isRealTimeCommand(char *cmd, size_t len) { return false; }
111-
112110
// check if current line is an [ESPXXX] command
113111
bool ESP3DCommands::is_esp_command(uint8_t *sbuf, size_t len) {
114112
// TODO
@@ -1156,10 +1154,6 @@ bool ESP3DCommands::dispatchIdValue(bool json, const char *Id,
11561154
}
11571155

11581156
bool ESP3DCommands::formatCommand(char *cmd, size_t len) {
1159-
if (isRealTimeCommand(cmd, len)) {
1160-
// TODO: what if is realtime command ?
1161-
return true;
1162-
}
11631157
uint sizestr = strlen(cmd);
11641158
if (len > sizestr + 2) {
11651159
cmd[sizestr] = '\n';
@@ -1205,10 +1199,6 @@ void ESP3DCommands::process(ESP3DMessage *msg) {
12051199
esp3d_log("Execute internal command %d", cmdId);
12061200
execute_internal_command(cmdId, espcmdpos, msg);
12071201
} else {
1208-
/*esp3d_log("Dispatch command, len %d, from %d(%s) to %d(%s)", msg->size,
1209-
static_cast<uint8_t>(msg->origin), GETCLIENTSTR(msg->origin),
1210-
static_cast<uint8_t>(msg->target), GETCLIENTSTR(msg->target));*/
1211-
12121202
// Work around to avoid to dispatch single \n or \r to everyone as it is
12131203
// part of previous ESP3D command
12141204
if (msg->size == 1 &&
@@ -1237,7 +1227,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg, uint8_t *sbuf, size_t len) {
12371227
// check is need \n at the end of the command
12381228
if (msg->type == ESP3DMessageType::unique ||
12391229
msg->type == ESP3DMessageType::tail) {
1240-
esp3d_log("unique or tail message :*%s*", (char *)sbuf);
1230+
esp3d_log_d("unique or tail message :*%s*", (char *)sbuf);
12411231
if (!formatCommand((char *)sbuf, len)) {
12421232
esp3d_log("format command failed");
12431233
String tmpstr = "";
@@ -1254,7 +1244,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg, uint8_t *sbuf, size_t len) {
12541244
return false;
12551245
}
12561246
} else {
1257-
esp3d_log("format command success, no need to update");
1247+
esp3d_log_d("format command success, no need to update");
12581248
if (!esp3d_message_manager.setDataContent(msg, sbuf, len)) {
12591249
esp3d_log_e("set data content failed");
12601250
esp3d_message_manager.deleteMsg(msg);
@@ -1263,6 +1253,9 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg, uint8_t *sbuf, size_t len) {
12631253
}
12641254
} else {
12651255
esp3d_log("not unique or tail message");
1256+
if (msg->type == ESP3DMessageType::realtimecmd){
1257+
esp3d_log_d("realtime command");
1258+
}
12661259
if (!esp3d_message_manager.setDataContent(msg, sbuf, len)) {
12671260
esp3d_log_e("set data content failed");
12681261
esp3d_message_manager.deleteMsg(msg);
@@ -1472,6 +1465,12 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
14721465

14731466
#ifdef PRINTER_HAS_DISPLAY
14741467
case ESP3DClientType::remote_screen:
1468+
if (ESP3DSettings::GetFirmwareTarget() == GRBL ||
1469+
ESP3DSettings::GetFirmwareTarget() == GRBLHAL) {
1470+
esp3d_log_e("Remote screen message is not supported for GRBL");
1471+
sendOk = false;
1472+
break;
1473+
}
14751474
esp3d_log("Remote screen message");
14761475
// change target to output client
14771476
msg->target = getOutputClient();

esp3d/src/core/esp3d_commands.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,6 @@ class ESP3DCommands {
227227
bool isFirst = false);
228228
bool dispatchAuthenticationError(ESP3DMessage* msg, uint cmdid, bool json);
229229
bool formatCommand(char* cmd, size_t len);
230-
bool isRealTimeCommand(char* cmd, size_t len);
231230
ESP3DClientType getOutputClient(bool fromSettings = false);
232231
void setOutputClient(ESP3DClientType output_client) {
233232
_output_client = output_client;

esp3d/src/core/esp3d_message.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class WebServer;
6060
#endif //pdTRUE
6161
#endif //ESP8266
6262

63-
enum class ESP3DMessageType : uint8_t { head, core, tail, unique };
63+
enum class ESP3DMessageType : uint8_t { head, core, tail, unique, realtimecmd };
6464

6565
union ESP3DRequest {
6666
uint id;

esp3d/src/core/esp3d_string.cpp

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <Arduino.h>
2323

2424
#include "../include/esp3d_config.h"
25+
#include "esp3d_settings.h"
2526

2627
#if defined(WIFI_FEATURE) || defined(ETH_FEATURE)
2728
#include "../modules/network/netconfig.h"
@@ -174,16 +175,16 @@ const char* esp3d_string::urlEncode(const char* s) {
174175
static String encoded;
175176
encoded = "";
176177
char temp[4];
177-
for (int i = 0; i < strlen(s); i++) {
178-
temp[0] =s[i];
179-
if (temp[0] == 32) { //space
178+
for (size_t i = 0; i < strlen(s); i++) {
179+
temp[0] = s[i];
180+
if (temp[0] == 32) { // space
180181
encoded.concat('+');
181-
} else if ((temp[0] >= 48 && temp[0] <= 57) /*0-9*/
182-
|| (temp[0] >= 65 && temp[0] <= 90) /*A-Z*/
183-
|| (temp[0] >= 97 && temp[0] <= 122) /*a-z*/
182+
} else if ((temp[0] >= 48 && temp[0] <= 57) /*0-9*/
183+
|| (temp[0] >= 65 && temp[0] <= 90) /*A-Z*/
184+
|| (temp[0] >= 97 && temp[0] <= 122) /*a-z*/
184185
) {
185186
encoded.concat(temp[0]);
186-
} else { //character needs encoding
187+
} else { // character needs encoding
187188
snprintf(temp, 4, "%%%02X", temp[0]);
188189
encoded.concat(temp);
189190
}
@@ -208,7 +209,7 @@ const char* esp3d_string::formatBytes(uint64_t bytes) {
208209

209210
bool esp3d_string::isPrintableChar(char ch) {
210211
int c = static_cast<int>(ch);
211-
if (c == 9 || (c >= 32 && c <= 126) || c >= 128) {
212+
if (c == '\t' || c == '\r' || (c >= ' ' && c <= '~') || c >= 128) {
212213
return true;
213214
}
214215
return false;
@@ -254,7 +255,7 @@ const char* esp3d_string::formatDuration(uint64_t duration) {
254255
display = true;
255256
}
256257
if (hours > 0 || display) {
257-
result+= String(hours) + "h ";
258+
result += String(hours) + "h ";
258259
display = true;
259260
}
260261
if (minutes > 0 || display) {
@@ -264,4 +265,21 @@ const char* esp3d_string::formatDuration(uint64_t duration) {
264265
result += String(seconds) + "s";
265266

266267
return result.c_str();
268+
}
269+
270+
bool esp3d_string::isRealTimeCommand(char c) {
271+
if (ESP3DSettings::GetFirmwareTarget() == GRBL ||
272+
ESP3DSettings::GetFirmwareTarget() == GRBLHAL) {
273+
// Standard characters
274+
if (c == '?' || c == '!' || c == '~' || c == 0x18) { // 0x18 is ^X
275+
return true;
276+
}
277+
278+
// Range >= 0x80 et <= 0xA4
279+
const unsigned char uc = static_cast<unsigned char>(c);
280+
if (uc >= 0x80 && uc <= 0xA4) {
281+
return true;
282+
}
283+
}
284+
return false;
267285
}

esp3d/src/core/esp3d_string.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const char* formatBytes(uint64_t bytes);
3131
bool isPrintableChar(char c);
3232
const char* expandString(const char* s, bool formatspace = false);
3333
const char * urlEncode(const char* s);
34+
bool isRealTimeCommand(char c);
3435
} // namespace esp3d_string
3536

3637
#endif //_ESP3D_STRING_H

esp3d/src/include/esp3d_version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#define _VERSION_ESP3D_H
2323

2424
// version and sources location
25-
#define FW_VERSION "3.0.0.a244"
25+
#define FW_VERSION "3.0.0.a245"
2626
#define REPOSITORY "https://github.com/luc-github/ESP3D/tree/3.0"
2727

2828
#endif //_VERSION_ESP3D_H

esp3d/src/modules/bluetooth/BT_service.cpp

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ void BTService::handle() {
176176
// we cannot left data in buffer too long
177177
// in case some commands "forget" to add \n
178178
if (((millis() - _lastflush) > TIMEOUT_BT_FLUSH) && (_buffer_size > 0)) {
179-
flushbuffer();
179+
flushBuffer();
180180
}
181181
}
182182

@@ -189,51 +189,48 @@ void BTService::initAuthentication() {
189189
}
190190
ESP3DAuthenticationLevel BTService::getAuthentication() { return _auth; }
191191

192-
void BTService::flushbuffer() {
193-
_buffer[_buffer_size] = 0x0;
194-
// dispatch command
195-
ESP3DMessage *msg = esp3d_message_manager.newMsg(
196-
ESP3DClientType::bluetooth, esp3d_commands.getOutputClient(), _buffer,
197-
_buffer_size, _auth);
198-
if (msg) {
199-
// process command
200-
esp3d_commands.process(msg);
192+
void BTService::flushData(const uint8_t *data, size_t size,
193+
ESP3DMessageType type) {
194+
ESP3DMessage *message = esp3d_message_manager.newMsg(
195+
ESP3DClientType::bluetooth, esp3d_commands.getOutputClient(), data,
196+
size, _auth);
197+
198+
if (message) {
199+
message->type = type;
200+
esp3d_log("Process Message");
201+
esp3d_commands.process(message);
201202
} else {
202203
esp3d_log_e("Cannot create message");
203204
}
204205
_lastflush = millis();
206+
}
207+
208+
void BTService::flushChar(char c) {
209+
flushData((uint8_t *)&c, 1, ESP3DMessageType::realtimecmd);
210+
}
211+
212+
void BTService::flushBuffer() {
213+
_buffer[_buffer_size] = 0x0;
214+
flushData((uint8_t *)_buffer, _buffer_size, ESP3DMessageType::unique);
205215
_buffer_size = 0;
206216
}
207217

208218
// push collected data to buffer and proceed accordingly
209219
void BTService::push2buffer(uint8_t *sbuf, size_t len) {
220+
if (!_buffer || !_started) {
221+
return;
222+
}
210223
for (size_t i = 0; i < len; i++) {
211224
_lastflush = millis();
212-
// command is defined
213-
if ((char(sbuf[i]) == '\n') || (char(sbuf[i]) == '\r')) {
214-
if (_buffer_size < ESP3D_BT_BUFFER_SIZE) {
215-
_buffer[_buffer_size] = sbuf[i];
216-
_buffer_size++;
217-
}
218-
flushbuffer();
219-
} else if (esp3d_string::isPrintableChar(char(sbuf[i]))) {
220-
if (_buffer_size < ESP3D_BT_BUFFER_SIZE) {
221-
_buffer[_buffer_size] = sbuf[i];
222-
_buffer_size++;
223-
} else {
224-
flushbuffer();
225-
_buffer[_buffer_size] = sbuf[i];
226-
_buffer_size++;
227-
}
228-
} else { // it is not printable char
229-
// clean buffer first
230-
if (_buffer_size > 0) {
231-
flushbuffer();
232-
}
233-
// process char
225+
if (esp3d_string::isRealTimeCommand(sbuf[i])) {
226+
flushChar(sbuf[i]);
227+
} else {
234228
_buffer[_buffer_size] = sbuf[i];
235229
_buffer_size++;
236-
flushbuffer();
230+
if (_buffer_size > ESP3D_BT_BUFFER_SIZE ||
231+
_buffer[_buffer_size - 1] == '\n') {
232+
flushBuffer();
233+
}
237234
}
238235
}
239236
}

esp3d/src/modules/bluetooth/BT_service.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ class BTService {
5757
uint8_t _buffer[ESP3D_BT_BUFFER_SIZE + 1]; // keep space of 0x0 terminal
5858
size_t _buffer_size;
5959
void push2buffer(uint8_t* sbuf, size_t len);
60-
void flushbuffer();
60+
void flushBuffer();
61+
void flushChar(char c);
62+
void flushData(const uint8_t* data, size_t size, ESP3DMessageType type);
6163
bool _started;
6264
};
6365

0 commit comments

Comments
 (0)