mirror of
https://git.mirrors.martin98.com/https://github.com/luc-github/ESP3D.git
synced 2025-08-13 16:09:05 +08:00
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
This commit is contained in:
parent
7b99d8a020
commit
fe23f0cb1e
@ -443,7 +443,7 @@
|
|||||||
/* Printer screen
|
/* Printer screen
|
||||||
* If your printer has a display
|
* If your printer has a display
|
||||||
*/
|
*/
|
||||||
#define PRINTER_HAS_DISPLAY
|
//#define PRINTER_HAS_DISPLAY
|
||||||
|
|
||||||
/* ESP3D screen
|
/* ESP3D screen
|
||||||
* Screen connected to ESP board
|
* Screen connected to ESP board
|
||||||
@ -644,9 +644,9 @@
|
|||||||
// LOG_OUTPUT_SERIAL2
|
// LOG_OUTPUT_SERIAL2
|
||||||
// LOG_OUTPUT_TELNET
|
// LOG_OUTPUT_TELNET
|
||||||
// LOG_OUTPUT_WEBSOCKET
|
// LOG_OUTPUT_WEBSOCKET
|
||||||
// #define ESP_LOG_FEATURE LOG_OUTPUT_SERIAL0
|
#define ESP_LOG_FEATURE LOG_OUTPUT_SERIAL0
|
||||||
|
|
||||||
// #define ESP3D_DEBUG_LEVEL LOG_LEVEL_DEBUG
|
#define ESP3D_DEBUG_LEVEL LOG_LEVEL_DEBUG
|
||||||
|
|
||||||
#ifdef ESP_LOG_FEATURE
|
#ifdef ESP_LOG_FEATURE
|
||||||
#define LOG_ESP3D_BAUDRATE 115200
|
#define LOG_ESP3D_BAUDRATE 115200
|
||||||
@ -657,7 +657,7 @@
|
|||||||
// #define ESP_BENCHMARK_FEATURE
|
// #define ESP_BENCHMARK_FEATURE
|
||||||
|
|
||||||
// Disable sanity check at compilation
|
// Disable sanity check at compilation
|
||||||
// #define ESP_NO_SANITY_CHECK
|
#define ESP_NO_SANITY_CHECK
|
||||||
|
|
||||||
/************************************
|
/************************************
|
||||||
*
|
*
|
||||||
|
@ -278,7 +278,7 @@ void Esp3D::restart_now() {
|
|||||||
#if defined(FILESYSTEM_FEATURE)
|
#if defined(FILESYSTEM_FEATURE)
|
||||||
ESP_FileSystem::end();
|
ESP_FileSystem::end();
|
||||||
#endif // FILESYSTEM_FEATURE
|
#endif // FILESYSTEM_FEATURE
|
||||||
#if COMMUNICATION_PROTOCOL == RAW_SERIAL || COMMUNICATION_PROTOCOL == MKS_SERIAL
|
#if (COMMUNICATION_PROTOCOL == RAW_SERIAL || COMMUNICATION_PROTOCOL == MKS_SERIAL) & defined(ARDUINO_ARCH_ESP8266)
|
||||||
esp3d_serial_service.swap();
|
esp3d_serial_service.swap();
|
||||||
#endif // COMMUNICATION_PROTOCOL == RAW_SERIAL || COMMUNICATION_PROTOCOL ==
|
#endif // COMMUNICATION_PROTOCOL == RAW_SERIAL || COMMUNICATION_PROTOCOL ==
|
||||||
// MKS_SERIAL
|
// MKS_SERIAL
|
||||||
|
@ -107,8 +107,6 @@ ESP3DCommands::ESP3DCommands() {
|
|||||||
|
|
||||||
ESP3DCommands::~ESP3DCommands() {}
|
ESP3DCommands::~ESP3DCommands() {}
|
||||||
|
|
||||||
bool ESP3DCommands::isRealTimeCommand(char *cmd, size_t len) { return false; }
|
|
||||||
|
|
||||||
// check if current line is an [ESPXXX] command
|
// check if current line is an [ESPXXX] command
|
||||||
bool ESP3DCommands::is_esp_command(uint8_t *sbuf, size_t len) {
|
bool ESP3DCommands::is_esp_command(uint8_t *sbuf, size_t len) {
|
||||||
// TODO
|
// TODO
|
||||||
@ -1156,10 +1154,6 @@ bool ESP3DCommands::dispatchIdValue(bool json, const char *Id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ESP3DCommands::formatCommand(char *cmd, size_t len) {
|
bool ESP3DCommands::formatCommand(char *cmd, size_t len) {
|
||||||
if (isRealTimeCommand(cmd, len)) {
|
|
||||||
// TODO: what if is realtime command ?
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
uint sizestr = strlen(cmd);
|
uint sizestr = strlen(cmd);
|
||||||
if (len > sizestr + 2) {
|
if (len > sizestr + 2) {
|
||||||
cmd[sizestr] = '\n';
|
cmd[sizestr] = '\n';
|
||||||
@ -1205,10 +1199,6 @@ void ESP3DCommands::process(ESP3DMessage *msg) {
|
|||||||
esp3d_log("Execute internal command %d", cmdId);
|
esp3d_log("Execute internal command %d", cmdId);
|
||||||
execute_internal_command(cmdId, espcmdpos, msg);
|
execute_internal_command(cmdId, espcmdpos, msg);
|
||||||
} else {
|
} else {
|
||||||
/*esp3d_log("Dispatch command, len %d, from %d(%s) to %d(%s)", msg->size,
|
|
||||||
static_cast<uint8_t>(msg->origin), GETCLIENTSTR(msg->origin),
|
|
||||||
static_cast<uint8_t>(msg->target), GETCLIENTSTR(msg->target));*/
|
|
||||||
|
|
||||||
// Work around to avoid to dispatch single \n or \r to everyone as it is
|
// Work around to avoid to dispatch single \n or \r to everyone as it is
|
||||||
// part of previous ESP3D command
|
// part of previous ESP3D command
|
||||||
if (msg->size == 1 &&
|
if (msg->size == 1 &&
|
||||||
@ -1237,7 +1227,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg, uint8_t *sbuf, size_t len) {
|
|||||||
// check is need \n at the end of the command
|
// check is need \n at the end of the command
|
||||||
if (msg->type == ESP3DMessageType::unique ||
|
if (msg->type == ESP3DMessageType::unique ||
|
||||||
msg->type == ESP3DMessageType::tail) {
|
msg->type == ESP3DMessageType::tail) {
|
||||||
esp3d_log("unique or tail message :*%s*", (char *)sbuf);
|
esp3d_log_d("unique or tail message :*%s*", (char *)sbuf);
|
||||||
if (!formatCommand((char *)sbuf, len)) {
|
if (!formatCommand((char *)sbuf, len)) {
|
||||||
esp3d_log("format command failed");
|
esp3d_log("format command failed");
|
||||||
String tmpstr = "";
|
String tmpstr = "";
|
||||||
@ -1254,7 +1244,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg, uint8_t *sbuf, size_t len) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
esp3d_log("format command success, no need to update");
|
esp3d_log_d("format command success, no need to update");
|
||||||
if (!esp3d_message_manager.setDataContent(msg, sbuf, len)) {
|
if (!esp3d_message_manager.setDataContent(msg, sbuf, len)) {
|
||||||
esp3d_log_e("set data content failed");
|
esp3d_log_e("set data content failed");
|
||||||
esp3d_message_manager.deleteMsg(msg);
|
esp3d_message_manager.deleteMsg(msg);
|
||||||
@ -1263,6 +1253,9 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg, uint8_t *sbuf, size_t len) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
esp3d_log("not unique or tail message");
|
esp3d_log("not unique or tail message");
|
||||||
|
if (msg->type == ESP3DMessageType::realtimecmd){
|
||||||
|
esp3d_log_d("realtime command");
|
||||||
|
}
|
||||||
if (!esp3d_message_manager.setDataContent(msg, sbuf, len)) {
|
if (!esp3d_message_manager.setDataContent(msg, sbuf, len)) {
|
||||||
esp3d_log_e("set data content failed");
|
esp3d_log_e("set data content failed");
|
||||||
esp3d_message_manager.deleteMsg(msg);
|
esp3d_message_manager.deleteMsg(msg);
|
||||||
@ -1472,6 +1465,12 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
|
|||||||
|
|
||||||
#ifdef PRINTER_HAS_DISPLAY
|
#ifdef PRINTER_HAS_DISPLAY
|
||||||
case ESP3DClientType::remote_screen:
|
case ESP3DClientType::remote_screen:
|
||||||
|
if (ESP3DSettings::GetFirmwareTarget() == GRBL ||
|
||||||
|
ESP3DSettings::GetFirmwareTarget() == GRBLHAL) {
|
||||||
|
esp3d_log_e("Remote screen message is not supported for GRBL");
|
||||||
|
sendOk = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
esp3d_log("Remote screen message");
|
esp3d_log("Remote screen message");
|
||||||
// change target to output client
|
// change target to output client
|
||||||
msg->target = getOutputClient();
|
msg->target = getOutputClient();
|
||||||
|
@ -227,7 +227,6 @@ class ESP3DCommands {
|
|||||||
bool isFirst = false);
|
bool isFirst = false);
|
||||||
bool dispatchAuthenticationError(ESP3DMessage* msg, uint cmdid, bool json);
|
bool dispatchAuthenticationError(ESP3DMessage* msg, uint cmdid, bool json);
|
||||||
bool formatCommand(char* cmd, size_t len);
|
bool formatCommand(char* cmd, size_t len);
|
||||||
bool isRealTimeCommand(char* cmd, size_t len);
|
|
||||||
ESP3DClientType getOutputClient(bool fromSettings = false);
|
ESP3DClientType getOutputClient(bool fromSettings = false);
|
||||||
void setOutputClient(ESP3DClientType output_client) {
|
void setOutputClient(ESP3DClientType output_client) {
|
||||||
_output_client = output_client;
|
_output_client = output_client;
|
||||||
|
@ -60,7 +60,7 @@ class WebServer;
|
|||||||
#endif //pdTRUE
|
#endif //pdTRUE
|
||||||
#endif //ESP8266
|
#endif //ESP8266
|
||||||
|
|
||||||
enum class ESP3DMessageType : uint8_t { head, core, tail, unique };
|
enum class ESP3DMessageType : uint8_t { head, core, tail, unique, realtimecmd };
|
||||||
|
|
||||||
union ESP3DRequest {
|
union ESP3DRequest {
|
||||||
uint id;
|
uint id;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
#include "../include/esp3d_config.h"
|
#include "../include/esp3d_config.h"
|
||||||
|
#include "esp3d_settings.h"
|
||||||
|
|
||||||
#if defined(WIFI_FEATURE) || defined(ETH_FEATURE)
|
#if defined(WIFI_FEATURE) || defined(ETH_FEATURE)
|
||||||
#include "../modules/network/netconfig.h"
|
#include "../modules/network/netconfig.h"
|
||||||
@ -174,7 +175,7 @@ const char* esp3d_string::urlEncode(const char* s) {
|
|||||||
static String encoded;
|
static String encoded;
|
||||||
encoded = "";
|
encoded = "";
|
||||||
char temp[4];
|
char temp[4];
|
||||||
for (int i = 0; i < strlen(s); i++) {
|
for (size_t i = 0; i < strlen(s); i++) {
|
||||||
temp[0] = s[i];
|
temp[0] = s[i];
|
||||||
if (temp[0] == 32) { // space
|
if (temp[0] == 32) { // space
|
||||||
encoded.concat('+');
|
encoded.concat('+');
|
||||||
@ -208,7 +209,7 @@ const char* esp3d_string::formatBytes(uint64_t bytes) {
|
|||||||
|
|
||||||
bool esp3d_string::isPrintableChar(char ch) {
|
bool esp3d_string::isPrintableChar(char ch) {
|
||||||
int c = static_cast<int>(ch);
|
int c = static_cast<int>(ch);
|
||||||
if (c == 9 || (c >= 32 && c <= 126) || c >= 128) {
|
if (c == '\t' || c == '\r' || (c >= ' ' && c <= '~') || c >= 128) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -265,3 +266,20 @@ const char* esp3d_string::formatDuration(uint64_t duration) {
|
|||||||
|
|
||||||
return result.c_str();
|
return result.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool esp3d_string::isRealTimeCommand(char c) {
|
||||||
|
if (ESP3DSettings::GetFirmwareTarget() == GRBL ||
|
||||||
|
ESP3DSettings::GetFirmwareTarget() == GRBLHAL) {
|
||||||
|
// Standard characters
|
||||||
|
if (c == '?' || c == '!' || c == '~' || c == 0x18) { // 0x18 is ^X
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Range >= 0x80 et <= 0xA4
|
||||||
|
const unsigned char uc = static_cast<unsigned char>(c);
|
||||||
|
if (uc >= 0x80 && uc <= 0xA4) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
@ -31,6 +31,7 @@ const char* formatBytes(uint64_t bytes);
|
|||||||
bool isPrintableChar(char c);
|
bool isPrintableChar(char c);
|
||||||
const char* expandString(const char* s, bool formatspace = false);
|
const char* expandString(const char* s, bool formatspace = false);
|
||||||
const char * urlEncode(const char* s);
|
const char * urlEncode(const char* s);
|
||||||
|
bool isRealTimeCommand(char c);
|
||||||
} // namespace esp3d_string
|
} // namespace esp3d_string
|
||||||
|
|
||||||
#endif //_ESP3D_STRING_H
|
#endif //_ESP3D_STRING_H
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#define _VERSION_ESP3D_H
|
#define _VERSION_ESP3D_H
|
||||||
|
|
||||||
// version and sources location
|
// version and sources location
|
||||||
#define FW_VERSION "3.0.0.a244"
|
#define FW_VERSION "3.0.0.a245"
|
||||||
#define REPOSITORY "https://github.com/luc-github/ESP3D/tree/3.0"
|
#define REPOSITORY "https://github.com/luc-github/ESP3D/tree/3.0"
|
||||||
|
|
||||||
#endif //_VERSION_ESP3D_H
|
#endif //_VERSION_ESP3D_H
|
||||||
|
@ -176,7 +176,7 @@ void BTService::handle() {
|
|||||||
// we cannot left data in buffer too long
|
// we cannot left data in buffer too long
|
||||||
// in case some commands "forget" to add \n
|
// in case some commands "forget" to add \n
|
||||||
if (((millis() - _lastflush) > TIMEOUT_BT_FLUSH) && (_buffer_size > 0)) {
|
if (((millis() - _lastflush) > TIMEOUT_BT_FLUSH) && (_buffer_size > 0)) {
|
||||||
flushbuffer();
|
flushBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,51 +189,48 @@ void BTService::initAuthentication() {
|
|||||||
}
|
}
|
||||||
ESP3DAuthenticationLevel BTService::getAuthentication() { return _auth; }
|
ESP3DAuthenticationLevel BTService::getAuthentication() { return _auth; }
|
||||||
|
|
||||||
void BTService::flushbuffer() {
|
void BTService::flushData(const uint8_t *data, size_t size,
|
||||||
_buffer[_buffer_size] = 0x0;
|
ESP3DMessageType type) {
|
||||||
// dispatch command
|
ESP3DMessage *message = esp3d_message_manager.newMsg(
|
||||||
ESP3DMessage *msg = esp3d_message_manager.newMsg(
|
ESP3DClientType::bluetooth, esp3d_commands.getOutputClient(), data,
|
||||||
ESP3DClientType::bluetooth, esp3d_commands.getOutputClient(), _buffer,
|
size, _auth);
|
||||||
_buffer_size, _auth);
|
|
||||||
if (msg) {
|
if (message) {
|
||||||
// process command
|
message->type = type;
|
||||||
esp3d_commands.process(msg);
|
esp3d_log("Process Message");
|
||||||
|
esp3d_commands.process(message);
|
||||||
} else {
|
} else {
|
||||||
esp3d_log_e("Cannot create message");
|
esp3d_log_e("Cannot create message");
|
||||||
}
|
}
|
||||||
_lastflush = millis();
|
_lastflush = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTService::flushChar(char c) {
|
||||||
|
flushData((uint8_t *)&c, 1, ESP3DMessageType::realtimecmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTService::flushBuffer() {
|
||||||
|
_buffer[_buffer_size] = 0x0;
|
||||||
|
flushData((uint8_t *)_buffer, _buffer_size, ESP3DMessageType::unique);
|
||||||
_buffer_size = 0;
|
_buffer_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// push collected data to buffer and proceed accordingly
|
// push collected data to buffer and proceed accordingly
|
||||||
void BTService::push2buffer(uint8_t *sbuf, size_t len) {
|
void BTService::push2buffer(uint8_t *sbuf, size_t len) {
|
||||||
|
if (!_buffer || !_started) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
_lastflush = millis();
|
_lastflush = millis();
|
||||||
// command is defined
|
if (esp3d_string::isRealTimeCommand(sbuf[i])) {
|
||||||
if ((char(sbuf[i]) == '\n') || (char(sbuf[i]) == '\r')) {
|
flushChar(sbuf[i]);
|
||||||
if (_buffer_size < ESP3D_BT_BUFFER_SIZE) {
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
|
||||||
_buffer_size++;
|
|
||||||
}
|
|
||||||
flushbuffer();
|
|
||||||
} else if (esp3d_string::isPrintableChar(char(sbuf[i]))) {
|
|
||||||
if (_buffer_size < ESP3D_BT_BUFFER_SIZE) {
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
|
||||||
_buffer_size++;
|
|
||||||
} else {
|
} else {
|
||||||
flushbuffer();
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
_buffer[_buffer_size] = sbuf[i];
|
||||||
_buffer_size++;
|
_buffer_size++;
|
||||||
|
if (_buffer_size > ESP3D_BT_BUFFER_SIZE ||
|
||||||
|
_buffer[_buffer_size - 1] == '\n') {
|
||||||
|
flushBuffer();
|
||||||
}
|
}
|
||||||
} else { // it is not printable char
|
|
||||||
// clean buffer first
|
|
||||||
if (_buffer_size > 0) {
|
|
||||||
flushbuffer();
|
|
||||||
}
|
|
||||||
// process char
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
|
||||||
_buffer_size++;
|
|
||||||
flushbuffer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,9 @@ class BTService {
|
|||||||
uint8_t _buffer[ESP3D_BT_BUFFER_SIZE + 1]; // keep space of 0x0 terminal
|
uint8_t _buffer[ESP3D_BT_BUFFER_SIZE + 1]; // keep space of 0x0 terminal
|
||||||
size_t _buffer_size;
|
size_t _buffer_size;
|
||||||
void push2buffer(uint8_t* sbuf, size_t len);
|
void push2buffer(uint8_t* sbuf, size_t len);
|
||||||
void flushbuffer();
|
void flushBuffer();
|
||||||
|
void flushChar(char c);
|
||||||
|
void flushData(const uint8_t* data, size_t size, ESP3DMessageType type);
|
||||||
bool _started;
|
bool _started;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ bool GcodeHost::push(const uint8_t *sbuf, size_t len) {
|
|||||||
esp3d_log("Push got %d bytes", len);
|
esp3d_log("Push got %d bytes", len);
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
// it is a line process it
|
// it is a line process it
|
||||||
if (sbuf[i] == '\n' || sbuf[i] == '\r') {
|
if (sbuf[i] == '\n') {
|
||||||
flush();
|
flush();
|
||||||
} else {
|
} else {
|
||||||
// fill buffer until it is full
|
// fill buffer until it is full
|
||||||
@ -263,7 +263,7 @@ void GcodeHost::readNextCommand() {
|
|||||||
} else {
|
} else {
|
||||||
_processedSize++;
|
_processedSize++;
|
||||||
_currentPosition++;
|
_currentPosition++;
|
||||||
if (!(((char)c == '\n') || ((char)c == '\r'))) {
|
if (!((char)c == '\n')) {
|
||||||
_currentCommand += (char)c;
|
_currentCommand += (char)c;
|
||||||
} else {
|
} else {
|
||||||
processing = false;
|
processing = false;
|
||||||
@ -290,7 +290,7 @@ void GcodeHost::readNextCommand() {
|
|||||||
} else {
|
} else {
|
||||||
_processedSize++;
|
_processedSize++;
|
||||||
_currentPosition++;
|
_currentPosition++;
|
||||||
if (!(((char)c == '\n') || ((char)c == '\r'))) {
|
if (!(char)c == '\n' ) {
|
||||||
_currentCommand += (char)c;
|
_currentCommand += (char)c;
|
||||||
} else {
|
} else {
|
||||||
processing = false;
|
processing = false;
|
||||||
|
@ -29,19 +29,9 @@
|
|||||||
#include "../../../core/esp3d_commands.h"
|
#include "../../../core/esp3d_commands.h"
|
||||||
#include "../../../core/esp3d_message.h"
|
#include "../../../core/esp3d_message.h"
|
||||||
#include "../../../core/esp3d_settings.h"
|
#include "../../../core/esp3d_settings.h"
|
||||||
|
#include "../../../core/esp3d_string.h"
|
||||||
#include "../../authentication/authentication_service.h"
|
#include "../../authentication/authentication_service.h"
|
||||||
|
|
||||||
const unsigned char realTimeCommands[] = {
|
|
||||||
'!', '~', '?', 0x18, 0x84, 0x85, 0x90, 0x92, 0x93, 0x94, 0x95,
|
|
||||||
0x96, 0x97, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0xA0, 0xA1};
|
|
||||||
bool isRealTimeCommand(unsigned char c) {
|
|
||||||
for (unsigned int i = 0; i < sizeof(realTimeCommands); i++) {
|
|
||||||
if (c == realTimeCommands[i]) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle web command query and send answer//////////////////////////////
|
// Handle web command query and send answer//////////////////////////////
|
||||||
void HTTP_Server::handle_web_command() {
|
void HTTP_Server::handle_web_command() {
|
||||||
@ -53,32 +43,42 @@ void HTTP_Server::handle_web_command() {
|
|||||||
}
|
}
|
||||||
// esp3d_log("Authentication = %d", auth_level);
|
// esp3d_log("Authentication = %d", auth_level);
|
||||||
String cmd = "";
|
String cmd = "";
|
||||||
|
bool isRealTimeCommand = false;
|
||||||
if (_webserver->hasArg("cmd")) {
|
if (_webserver->hasArg("cmd")) {
|
||||||
cmd = _webserver->arg("cmd");
|
cmd = _webserver->arg("cmd");
|
||||||
|
esp3d_log_d("Command is %s", cmd.c_str());
|
||||||
if (!cmd.endsWith("\n")) {
|
if (!cmd.endsWith("\n")) {
|
||||||
if (ESP3DSettings::GetFirmwareTarget() == GRBL) {
|
esp3d_log_d("Command is not ending with \\n");
|
||||||
|
if (ESP3DSettings::GetFirmwareTarget() == GRBL || ESP3DSettings::GetFirmwareTarget() == GRBLHAL) {
|
||||||
uint len = cmd.length();
|
uint len = cmd.length();
|
||||||
if (!((len == 1 && isRealTimeCommand(cmd[0])) ||
|
if (!((len == 1 && esp3d_string::isRealTimeCommand(cmd[0])) ||
|
||||||
(len == 2 && isRealTimeCommand(cmd[1])))) {
|
(len == 2 && esp3d_string::isRealTimeCommand(cmd[1])))) {
|
||||||
cmd += "\n";
|
cmd += "\n";
|
||||||
|
esp3d_log_d("Command is not realtime, adding \\n");
|
||||||
} else { // no need \n for realtime command
|
} else { // no need \n for realtime command
|
||||||
|
esp3d_log_d("Command is realtime, no need to add \\n");
|
||||||
|
isRealTimeCommand = true;
|
||||||
// remove the 0XC2 that should not be there
|
// remove the 0XC2 that should not be there
|
||||||
if (len == 2 && isRealTimeCommand(cmd[1]) && cmd[1] == 0xC2) {
|
if (len == 2 && esp3d_string::isRealTimeCommand(cmd[1]) && cmd[1] == 0xC2) {
|
||||||
cmd[0] = cmd[1];
|
cmd[0] = cmd[1];
|
||||||
cmd[1] = 0x0;
|
cmd[1] = 0x0;
|
||||||
|
esp3d_log_d("Command is realtime, removing 0xC2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
esp3d_log_d("Command is not realtime, adding \\n");
|
||||||
cmd += "\n"; // need to validate command
|
cmd += "\n"; // need to validate command
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
esp3d_log_d("Command is ending with \\n");
|
||||||
}
|
}
|
||||||
esp3d_log("Web Command: %s", cmd.c_str());
|
esp3d_log_d("Message type is %s for %s", isRealTimeCommand ? "realtimecmd" : "unique", cmd.c_str());
|
||||||
if (esp3d_commands.is_esp_command((uint8_t *)cmd.c_str(), cmd.length())) {
|
if (esp3d_commands.is_esp_command((uint8_t *)cmd.c_str(), cmd.length())) {
|
||||||
ESP3DMessage *msg = esp3d_message_manager.newMsg(
|
ESP3DMessage *msg = esp3d_message_manager.newMsg(
|
||||||
ESP3DClientType::http, esp3d_commands.getOutputClient(),
|
ESP3DClientType::http, esp3d_commands.getOutputClient(),
|
||||||
(uint8_t *)cmd.c_str(), cmd.length(), auth_level);
|
(uint8_t *)cmd.c_str(), cmd.length(), auth_level);
|
||||||
if (msg) {
|
if (msg) {
|
||||||
msg->type = ESP3DMessageType::unique;
|
msg->type = ESP3DMessageType::unique; //ESP3D command is always unique
|
||||||
msg->request_id.code = 200;
|
msg->request_id.code = 200;
|
||||||
// process command
|
// process command
|
||||||
esp3d_commands.process(msg);
|
esp3d_commands.process(msg);
|
||||||
@ -91,7 +91,7 @@ void HTTP_Server::handle_web_command() {
|
|||||||
// no need to wait to answer then
|
// no need to wait to answer then
|
||||||
_webserver->send(200, "text/plain", "ESP3D says: command forwarded");
|
_webserver->send(200, "text/plain", "ESP3D says: command forwarded");
|
||||||
esp3d_commands.dispatch(cmd.c_str(), esp3d_commands.getOutputClient(),
|
esp3d_commands.dispatch(cmd.c_str(), esp3d_commands.getOutputClient(),
|
||||||
no_id, ESP3DMessageType::unique,
|
no_id, isRealTimeCommand ? ESP3DMessageType::realtimecmd :ESP3DMessageType::unique,
|
||||||
ESP3DClientType::http, auth_level);
|
ESP3DClientType::http, auth_level);
|
||||||
}
|
}
|
||||||
} else if (_webserver->hasArg("ping")) {
|
} else if (_webserver->hasArg("ping")) {
|
||||||
|
@ -257,7 +257,8 @@ bool HTTP_Server::dispatch(ESP3DMessage* msg) {
|
|||||||
}
|
}
|
||||||
if ((msg->size > 0 && msg->data) || (msg->type == ESP3DMessageType::tail)) {
|
if ((msg->size > 0 && msg->data) || (msg->type == ESP3DMessageType::tail)) {
|
||||||
if (msg->type == ESP3DMessageType::head ||
|
if (msg->type == ESP3DMessageType::head ||
|
||||||
msg->type == ESP3DMessageType::unique) {
|
msg->type == ESP3DMessageType::unique ||
|
||||||
|
msg->type == ESP3DMessageType::realtimecmd) {
|
||||||
set_http_headers();
|
set_http_headers();
|
||||||
int code = 200;
|
int code = 200;
|
||||||
if (msg->request_id.code != 0) {
|
if (msg->request_id.code != 0) {
|
||||||
|
176
esp3d/src/modules/serial/serial_service.cpp
Normal file
176
esp3d/src/modules/serial/serial_service.cpp
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
esp3d_serial_service.cpp - serial services functions class
|
||||||
|
|
||||||
|
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
||||||
|
|
||||||
|
This code is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This code is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with This code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include "../../include/esp3d_config.h"
|
||||||
|
#if COMMUNICATION_PROTOCOL == RAW_SERIAL || \
|
||||||
|
defined(ESP_SERIAL_BRIDGE_OUTPUT) || COMMUNICATION_PROTOCOL == MKS_SERIAL
|
||||||
|
#include "../../core/esp3d_commands.h"
|
||||||
|
#include "../../core/esp3d_settings.h"
|
||||||
|
#include "../../core/esp3d_string.h"
|
||||||
|
#include "../authentication/authentication_service.h"
|
||||||
|
#include "serial_service.h"
|
||||||
|
|
||||||
|
extern HardwareSerial *Serials[];
|
||||||
|
|
||||||
|
// Serial Parameters
|
||||||
|
|
||||||
|
ESP3DSerialService esp3d_serial_service = ESP3DSerialService(MAIN_SERIAL);
|
||||||
|
#if defined(ESP_SERIAL_BRIDGE_OUTPUT)
|
||||||
|
ESP3DSerialService serial_bridge_service = ESP3DSerialService(BRIDGE_SERIAL);
|
||||||
|
#endif // ESP_SERIAL_BRIDGE_OUTPUT
|
||||||
|
|
||||||
|
const uint32_t SupportedBaudList[] = {9600, 19200, 38400, 57600, 74880,
|
||||||
|
115200, 230400, 250000, 500000, 921600,
|
||||||
|
1000000, 1958400, 2000000};
|
||||||
|
const size_t SupportedBaudListSize =
|
||||||
|
sizeof(SupportedBaudList) / sizeof(uint32_t);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
ESP3DSerialService::~ESP3DSerialService() { end(); }
|
||||||
|
|
||||||
|
// extra parameters that do not need a begin
|
||||||
|
void ESP3DSerialService::setParameters() {
|
||||||
|
#if defined(AUTHENTICATION_FEATURE)
|
||||||
|
_needauthentication =
|
||||||
|
(ESP3DSettings::readByte(ESP_SECURE_SERIAL) == 0) ? false : true;
|
||||||
|
#else
|
||||||
|
_needauthentication = false;
|
||||||
|
#endif // AUTHENTICATION_FEATURE
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP3DSerialService::initAuthentication() {
|
||||||
|
#if defined(AUTHENTICATION_FEATURE)
|
||||||
|
_auth = ESP3DAuthenticationLevel::guest;
|
||||||
|
#else
|
||||||
|
_auth = ESP3DAuthenticationLevel::admin;
|
||||||
|
#endif // AUTHENTICATION_FEATURE
|
||||||
|
}
|
||||||
|
ESP3DAuthenticationLevel ESP3DSerialService::getAuthentication() {
|
||||||
|
if (_needauthentication) {
|
||||||
|
return _auth;
|
||||||
|
}
|
||||||
|
return ESP3DAuthenticationLevel::admin;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return the array of uint32_t and array size
|
||||||
|
const uint32_t *ESP3DSerialService::get_baudratelist(uint8_t *count) {
|
||||||
|
if (count) {
|
||||||
|
*count = sizeof(SupportedBaudList) / sizeof(uint32_t);
|
||||||
|
}
|
||||||
|
return SupportedBaudList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ESP3DSerialService::flushChar(char c) { flushData((uint8_t *)&c, 1, ESP3DMessageType::realtimecmd); }
|
||||||
|
|
||||||
|
void ESP3DSerialService::flushBuffer() {
|
||||||
|
_buffer[_buffer_size] = 0x0;
|
||||||
|
flushData((uint8_t *)_buffer, _buffer_size, ESP3DMessageType::unique);
|
||||||
|
_buffer_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ESP3DSerialService::updateBaudRate(uint32_t br) {
|
||||||
|
if (br != _baudRate) {
|
||||||
|
Serials[_serialIndex]->flush();
|
||||||
|
Serials[_serialIndex]->updateBaudRate(br);
|
||||||
|
_baudRate = br;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get current baud rate
|
||||||
|
uint32_t ESP3DSerialService::baudRate() { return _baudRate; }
|
||||||
|
|
||||||
|
size_t ESP3DSerialService::writeBytes(const uint8_t *buffer, size_t size) {
|
||||||
|
if (!_started) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ((uint)Serials[_serialIndex]->availableForWrite() >= size) {
|
||||||
|
return Serials[_serialIndex]->write(buffer, size);
|
||||||
|
} else {
|
||||||
|
size_t sizetosend = size;
|
||||||
|
size_t sizesent = 0;
|
||||||
|
uint8_t *buffertmp = (uint8_t *)buffer;
|
||||||
|
uint32_t starttime = millis();
|
||||||
|
// loop until all is sent or timeout
|
||||||
|
while (sizetosend > 0 && ((millis() - starttime) < 100)) {
|
||||||
|
size_t available = Serials[_serialIndex]->availableForWrite();
|
||||||
|
if (available > 0) {
|
||||||
|
// in case less is sent
|
||||||
|
available = Serials[_serialIndex]->write(
|
||||||
|
&buffertmp[sizesent],
|
||||||
|
(available >= sizetosend) ? sizetosend : available);
|
||||||
|
sizetosend -= available;
|
||||||
|
sizesent += available;
|
||||||
|
starttime = millis();
|
||||||
|
} else {
|
||||||
|
ESP3DHal::wait(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sizesent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ESP3DSerialService::readBytes(uint8_t *sbuf, size_t len) {
|
||||||
|
if (!_started) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return Serials[_serialIndex]->readBytes(sbuf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP3DSerialService::flush() {
|
||||||
|
if (!_started) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Serials[_serialIndex]->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ESP3DSerialService::dispatch(ESP3DMessage *message) {
|
||||||
|
bool done = false;
|
||||||
|
// Only is serial service is started
|
||||||
|
if (_started) {
|
||||||
|
// Only if message is not null
|
||||||
|
if (message) {
|
||||||
|
// if message is not null
|
||||||
|
if (message->data && message->size != 0) {
|
||||||
|
if (writeBytes(message->data, message->size) == message->size) {
|
||||||
|
flush();
|
||||||
|
// Delete message now
|
||||||
|
esp3d_message_manager.deleteMsg(message);
|
||||||
|
done = true;
|
||||||
|
} else {
|
||||||
|
esp3d_log_e("Error while sending data");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
esp3d_log_e("Error null data");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
esp3d_log_e("Error null message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // COMMUNICATION_PROTOCOL == RAW_SERIAL ||
|
||||||
|
// defined(ESP_SERIAL_BRIDGE_OUTPUT)
|
@ -29,6 +29,7 @@
|
|||||||
#endif // ARDUINO_ARCH_ESP32
|
#endif // ARDUINO_ARCH_ESP32
|
||||||
|
|
||||||
#define ESP3D_SERIAL_BUFFER_SIZE 1024
|
#define ESP3D_SERIAL_BUFFER_SIZE 1024
|
||||||
|
#define ESP_SERIAL_PARAM SERIAL_8N1
|
||||||
|
|
||||||
extern const uint32_t SupportedBaudList[];
|
extern const uint32_t SupportedBaudList[];
|
||||||
extern const size_t SupportedBaudListSize;
|
extern const size_t SupportedBaudListSize;
|
||||||
@ -47,7 +48,9 @@ class ESP3DSerialService final {
|
|||||||
uint8_t serialIndex() { return _serialIndex; }
|
uint8_t serialIndex() { return _serialIndex; }
|
||||||
const uint32_t *get_baudratelist(uint8_t *count);
|
const uint32_t *get_baudratelist(uint8_t *count);
|
||||||
void flush();
|
void flush();
|
||||||
|
#if defined(ARDUINO_ARCH_ESP8266)
|
||||||
void swap();
|
void swap();
|
||||||
|
#endif // ARDUINO_ARCH_ESP8266
|
||||||
size_t writeBytes(const uint8_t *buffer, size_t size);
|
size_t writeBytes(const uint8_t *buffer, size_t size);
|
||||||
size_t readBytes(uint8_t *sbuf, size_t len);
|
size_t readBytes(uint8_t *sbuf, size_t len);
|
||||||
inline bool started() { return _started; }
|
inline bool started() { return _started; }
|
||||||
@ -77,8 +80,12 @@ class ESP3DSerialService final {
|
|||||||
SemaphoreHandle_t _mutex;
|
SemaphoreHandle_t _mutex;
|
||||||
ESP3DMessageFIFO _messagesInFIFO;
|
ESP3DMessageFIFO _messagesInFIFO;
|
||||||
#endif // ARDUINO_ARCH_ESP32
|
#endif // ARDUINO_ARCH_ESP32
|
||||||
|
#if defined(ARDUINO_ARCH_ESP8266)
|
||||||
void push2buffer(uint8_t *sbuf, size_t len);
|
void push2buffer(uint8_t *sbuf, size_t len);
|
||||||
void flushbuffer();
|
#endif // ARDUINO_ARCH_ESP8266
|
||||||
|
void flushBuffer();
|
||||||
|
void flushChar(char c);
|
||||||
|
void flushData(const uint8_t* data, size_t size, ESP3DMessageType type);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ESP3DSerialService esp3d_serial_service;
|
extern ESP3DSerialService esp3d_serial_service;
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
*/
|
*/
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
#include "../../include/esp3d_config.h"
|
#include "../../include/esp3d_config.h"
|
||||||
#if COMMUNICATION_PROTOCOL == RAW_SERIAL || defined(ESP_SERIAL_BRIDGE_OUTPUT) || COMMUNICATION_PROTOCOL == MKS_SERIAL
|
#if COMMUNICATION_PROTOCOL == RAW_SERIAL || \
|
||||||
|
defined(ESP_SERIAL_BRIDGE_OUTPUT) || COMMUNICATION_PROTOCOL == MKS_SERIAL
|
||||||
#include "../../core/esp3d_commands.h"
|
#include "../../core/esp3d_commands.h"
|
||||||
#include "../../core/esp3d_settings.h"
|
#include "../../core/esp3d_settings.h"
|
||||||
#include "../../core/esp3d_string.h"
|
#include "../../core/esp3d_string.h"
|
||||||
@ -38,19 +39,7 @@ HardwareSerial *Serials[MAX_SERIAL] = {&Serial, &Serial1, &Serial2};
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Serial Parameters
|
// Serial Parameters
|
||||||
#define ESP_SERIAL_PARAM SERIAL_8N1
|
|
||||||
|
|
||||||
ESP3DSerialService esp3d_serial_service = ESP3DSerialService(MAIN_SERIAL);
|
|
||||||
#if defined(ESP_SERIAL_BRIDGE_OUTPUT)
|
|
||||||
ESP3DSerialService serial_bridge_service = ESP3DSerialService(BRIDGE_SERIAL);
|
|
||||||
#endif // ESP_SERIAL_BRIDGE_OUTPUT
|
|
||||||
|
|
||||||
const uint32_t SupportedBaudList[] = {9600, 19200, 38400, 57600, 74880,
|
|
||||||
115200, 230400, 250000, 500000, 921600,
|
|
||||||
1000000, 1958400, 2000000};
|
|
||||||
const size_t SupportedBaudListSize = sizeof(SupportedBaudList) / sizeof(uint32_t);
|
|
||||||
|
|
||||||
#define TIMEOUT_SERIAL_FLUSH 1500
|
|
||||||
// Constructor
|
// Constructor
|
||||||
ESP3DSerialService::ESP3DSerialService(uint8_t id) {
|
ESP3DSerialService::ESP3DSerialService(uint8_t id) {
|
||||||
_buffer_size = 0;
|
_buffer_size = 0;
|
||||||
@ -85,34 +74,6 @@ ESP3DSerialService::ESP3DSerialService(uint8_t id) {
|
|||||||
_messagesInFIFO.setMaxSize(0); // no limit
|
_messagesInFIFO.setMaxSize(0); // no limit
|
||||||
_baudRate = 0;
|
_baudRate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
|
||||||
ESP3DSerialService::~ESP3DSerialService() { end(); }
|
|
||||||
|
|
||||||
// extra parameters that do not need a begin
|
|
||||||
void ESP3DSerialService::setParameters() {
|
|
||||||
#if defined(AUTHENTICATION_FEATURE)
|
|
||||||
_needauthentication =
|
|
||||||
(ESP3DSettings::readByte(ESP_SECURE_SERIAL) == 0) ? false : true;
|
|
||||||
#else
|
|
||||||
_needauthentication = false;
|
|
||||||
#endif // AUTHENTICATION_FEATURE
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESP3DSerialService::initAuthentication() {
|
|
||||||
#if defined(AUTHENTICATION_FEATURE)
|
|
||||||
_auth = ESP3DAuthenticationLevel::guest;
|
|
||||||
#else
|
|
||||||
_auth = ESP3DAuthenticationLevel::admin;
|
|
||||||
#endif // AUTHENTICATION_FEATURE
|
|
||||||
}
|
|
||||||
ESP3DAuthenticationLevel ESP3DSerialService::getAuthentication() {
|
|
||||||
if (_needauthentication) {
|
|
||||||
return _auth;
|
|
||||||
}
|
|
||||||
return ESP3DAuthenticationLevel::admin;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESP3DSerialService::receiveSerialCb() { esp3d_serial_service.receiveCb(); }
|
void ESP3DSerialService::receiveSerialCb() { esp3d_serial_service.receiveCb(); }
|
||||||
|
|
||||||
#if defined(ESP_SERIAL_BRIDGE_OUTPUT)
|
#if defined(ESP_SERIAL_BRIDGE_OUTPUT)
|
||||||
@ -130,15 +91,16 @@ void ESP3DSerialService::receiveCb() {
|
|||||||
while ((millis() - now) < SERIAL_COMMUNICATION_TIMEOUT) {
|
while ((millis() - now) < SERIAL_COMMUNICATION_TIMEOUT) {
|
||||||
if (Serials[_serialIndex]->available()) {
|
if (Serials[_serialIndex]->available()) {
|
||||||
_buffer[_buffer_size] = Serials[_serialIndex]->read();
|
_buffer[_buffer_size] = Serials[_serialIndex]->read();
|
||||||
_buffer_size++;
|
|
||||||
now = millis();
|
now = millis();
|
||||||
|
if (esp3d_string::isRealTimeCommand(_buffer[_buffer_size])) {
|
||||||
|
flushChar(_buffer[_buffer_size]);
|
||||||
|
_buffer[_buffer_size] = '\0'; //remove realtime command from buffer
|
||||||
|
} else {
|
||||||
|
_buffer_size++;
|
||||||
if (_buffer_size > ESP3D_SERIAL_BUFFER_SIZE ||
|
if (_buffer_size > ESP3D_SERIAL_BUFFER_SIZE ||
|
||||||
_buffer[_buffer_size - 1] == '\n' ||
|
_buffer[_buffer_size - 1] == '\n') {
|
||||||
_buffer[_buffer_size - 1] == '\r') {
|
flushBuffer();
|
||||||
if (_buffer[_buffer_size - 1] == '\r') {
|
|
||||||
_buffer[_buffer_size - 1] = '\n';
|
|
||||||
}
|
}
|
||||||
flushbuffer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -229,12 +191,21 @@ bool ESP3DSerialService::end() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the array of uint32_t and array size
|
void ESP3DSerialService::flushData(const uint8_t *data, size_t size, ESP3DMessageType type) {
|
||||||
const uint32_t *ESP3DSerialService::get_baudratelist(uint8_t *count) {
|
ESP3DMessage *message = esp3d_message_manager.newMsg(
|
||||||
if (count) {
|
_origin,
|
||||||
*count = sizeof(SupportedBaudList) / sizeof(uint32_t);
|
_id == MAIN_SERIAL ? ESP3DClientType::all_clients
|
||||||
|
: esp3d_commands.getOutputClient(),
|
||||||
|
data, size, getAuthentication());
|
||||||
|
|
||||||
|
if (message) {
|
||||||
|
message->type = type;
|
||||||
|
esp3d_log("Message sent to fifo list");
|
||||||
|
_messagesInFIFO.push(message);
|
||||||
|
} else {
|
||||||
|
esp3d_log_e("Cannot create message");
|
||||||
}
|
}
|
||||||
return SupportedBaudList;
|
_lastflush = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function which could be called in other loop
|
// Function which could be called in other loop
|
||||||
@ -258,68 +229,6 @@ void ESP3DSerialService::handle() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP3DSerialService::flushbuffer() {
|
|
||||||
_buffer[_buffer_size] = 0x0;
|
|
||||||
if (_buffer_size == 1 && _buffer[0] == '\n') {
|
|
||||||
_buffer_size = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// dispatch command
|
|
||||||
ESP3DMessage *message = esp3d_message_manager.newMsg(
|
|
||||||
_origin,
|
|
||||||
_id == MAIN_SERIAL ? ESP3DClientType::all_clients
|
|
||||||
: esp3d_commands.getOutputClient(),
|
|
||||||
(uint8_t *)_buffer, _buffer_size, getAuthentication());
|
|
||||||
if (message) {
|
|
||||||
// process command
|
|
||||||
message->type = ESP3DMessageType::unique;
|
|
||||||
esp3d_log("Message sent to fifo list");
|
|
||||||
_messagesInFIFO.push(message);
|
|
||||||
} else {
|
|
||||||
esp3d_log_e("Cannot create message");
|
|
||||||
}
|
|
||||||
_lastflush = millis();
|
|
||||||
_buffer_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// push collected data to buffer and proceed accordingly
|
|
||||||
void ESP3DSerialService::push2buffer(uint8_t *sbuf, size_t len) {
|
|
||||||
/* if (!_started) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
esp3d_log("buffer get %d data ", len);
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
|
||||||
_lastflush = millis();
|
|
||||||
// command is defined
|
|
||||||
if ((char(sbuf[i]) == '\n') || (char(sbuf[i]) == '\r')) {
|
|
||||||
if (_buffer_size < ESP3D_SERIAL_BUFFER_SIZE) {
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
|
||||||
_buffer_size++;
|
|
||||||
}
|
|
||||||
flushbuffer();
|
|
||||||
} else if (esp3d_string::isPrintableChar(char(sbuf[i]))) {
|
|
||||||
if (_buffer_size < ESP3D_SERIAL_BUFFER_SIZE) {
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
|
||||||
_buffer_size++;
|
|
||||||
} else {
|
|
||||||
flushbuffer();
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
|
||||||
_buffer_size++;
|
|
||||||
}
|
|
||||||
} else { // it is not printable char
|
|
||||||
// clean buffer first
|
|
||||||
if (_buffer_size > 0) {
|
|
||||||
flushbuffer();
|
|
||||||
}
|
|
||||||
// process char
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
|
||||||
_buffer_size++;
|
|
||||||
flushbuffer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/}
|
|
||||||
|
|
||||||
// Reset Serial Setting (baud rate)
|
// Reset Serial Setting (baud rate)
|
||||||
bool ESP3DSerialService::reset() {
|
bool ESP3DSerialService::reset() {
|
||||||
esp3d_log("Reset serial");
|
esp3d_log("Reset serial");
|
||||||
@ -334,8 +243,8 @@ void ESP3DSerialService::push2buffer(uint8_t *sbuf, size_t len) {
|
|||||||
res = ESP3DSettings::writeByte(
|
res = ESP3DSettings::writeByte(
|
||||||
ESP_SERIAL_BRIDGE_ON,
|
ESP_SERIAL_BRIDGE_ON,
|
||||||
ESP3DSettings::getDefaultByteSetting(ESP_SERIAL_BRIDGE_ON));
|
ESP3DSettings::getDefaultByteSetting(ESP_SERIAL_BRIDGE_ON));
|
||||||
return res && ESP3DSettings::writeUint32(
|
return res &&
|
||||||
ESP_SERIAL_BRIDGE_BAUD,
|
ESP3DSettings::writeUint32(ESP_SERIAL_BRIDGE_BAUD,
|
||||||
ESP3DSettings::getDefaultIntegerSetting(
|
ESP3DSettings::getDefaultIntegerSetting(
|
||||||
ESP_SERIAL_BRIDGE_BAUD));
|
ESP_SERIAL_BRIDGE_BAUD));
|
||||||
#endif // ESP_SERIAL_BRIDGE_OUTPUT
|
#endif // ESP_SERIAL_BRIDGE_OUTPUT
|
||||||
@ -344,93 +253,6 @@ void ESP3DSerialService::push2buffer(uint8_t *sbuf, size_t len) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP3DSerialService::updateBaudRate(uint32_t br) {
|
|
||||||
if (br != _baudRate) {
|
|
||||||
Serials[_serialIndex]->flush();
|
|
||||||
Serials[_serialIndex]->updateBaudRate(br);
|
|
||||||
_baudRate = br;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get current baud rate
|
|
||||||
uint32_t ESP3DSerialService::baudRate() {
|
|
||||||
|
|
||||||
return _baudRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ESP3DSerialService::writeBytes(const uint8_t *buffer, size_t size) {
|
|
||||||
if (!_started) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if ((uint)Serials[_serialIndex]->availableForWrite() >= size) {
|
|
||||||
return Serials[_serialIndex]->write(buffer, size);
|
|
||||||
} else {
|
|
||||||
size_t sizetosend = size;
|
|
||||||
size_t sizesent = 0;
|
|
||||||
uint8_t *buffertmp = (uint8_t *)buffer;
|
|
||||||
uint32_t starttime = millis();
|
|
||||||
// loop until all is sent or timeout
|
|
||||||
while (sizetosend > 0 && ((millis() - starttime) < 100)) {
|
|
||||||
size_t available = Serials[_serialIndex]->availableForWrite();
|
|
||||||
if (available > 0) {
|
|
||||||
// in case less is sent
|
|
||||||
available = Serials[_serialIndex]->write(
|
|
||||||
&buffertmp[sizesent],
|
|
||||||
(available >= sizetosend) ? sizetosend : available);
|
|
||||||
sizetosend -= available;
|
|
||||||
sizesent += available;
|
|
||||||
starttime = millis();
|
|
||||||
} else {
|
|
||||||
ESP3DHal::wait(5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sizesent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ESP3DSerialService::readBytes(uint8_t *sbuf, size_t len) {
|
|
||||||
if (!_started) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return Serials[_serialIndex]->readBytes(sbuf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESP3DSerialService::flush() {
|
|
||||||
if (!_started) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Serials[_serialIndex]->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESP3DSerialService::swap() {
|
|
||||||
// Nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ESP3DSerialService::dispatch(ESP3DMessage *message) {
|
|
||||||
bool done = false;
|
|
||||||
// Only is serial service is started
|
|
||||||
if (_started) {
|
|
||||||
// Only if message is not null
|
|
||||||
if (message) {
|
|
||||||
// if message is not null
|
|
||||||
if (message->data && message->size != 0) {
|
|
||||||
if (writeBytes(message->data, message->size) == message->size) {
|
|
||||||
flush();
|
|
||||||
// Delete message now
|
|
||||||
esp3d_message_manager.deleteMsg(message);
|
|
||||||
done = true;
|
|
||||||
} else {
|
|
||||||
esp3d_log_e("Error while sending data");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
esp3d_log_e("Error null data");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
esp3d_log_e("Error null message");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return done;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // COMMUNICATION_PROTOCOL == RAW_SERIAL ||
|
#endif // COMMUNICATION_PROTOCOL == RAW_SERIAL ||
|
||||||
// defined(ESP_SERIAL_BRIDGE_OUTPUT)
|
// defined(ESP_SERIAL_BRIDGE_OUTPUT)
|
||||||
|
@ -32,17 +32,10 @@
|
|||||||
#define MAX_SERIAL 2
|
#define MAX_SERIAL 2
|
||||||
HardwareSerial *Serials[MAX_SERIAL] = {&Serial, &Serial1};
|
HardwareSerial *Serials[MAX_SERIAL] = {&Serial, &Serial1};
|
||||||
|
|
||||||
// Serial Parameters
|
|
||||||
#define ESP_SERIAL_PARAM SERIAL_8N1
|
|
||||||
|
|
||||||
ESP3DSerialService esp3d_serial_service = ESP3DSerialService(MAIN_SERIAL);
|
|
||||||
|
|
||||||
const uint32_t SupportedBaudList[] = {9600, 19200, 38400, 57600, 74880,
|
|
||||||
115200, 230400, 250000, 500000, 921600,
|
|
||||||
1000000, 1958400, 2000000};
|
|
||||||
const size_t SupportedBaudListSize = sizeof(SupportedBaudList) / sizeof(uint32_t);
|
|
||||||
|
|
||||||
#define TIMEOUT_SERIAL_FLUSH 1500
|
#define TIMEOUT_SERIAL_FLUSH 1500
|
||||||
|
|
||||||
|
// Serial Parameters
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
ESP3DSerialService::ESP3DSerialService(uint8_t id) {
|
ESP3DSerialService::ESP3DSerialService(uint8_t id) {
|
||||||
_buffer_size = 0;
|
_buffer_size = 0;
|
||||||
@ -59,33 +52,6 @@ ESP3DSerialService::ESP3DSerialService(uint8_t id) {
|
|||||||
_origin = ESP3DClientType::serial;
|
_origin = ESP3DClientType::serial;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
|
||||||
ESP3DSerialService::~ESP3DSerialService() { end(); }
|
|
||||||
|
|
||||||
// extra parameters that do not need a begin
|
|
||||||
void ESP3DSerialService::setParameters() {
|
|
||||||
#if defined(AUTHENTICATION_FEATURE)
|
|
||||||
_needauthentication =
|
|
||||||
(ESP3DSettings::readByte(ESP_SECURE_SERIAL) == 0) ? false : true;
|
|
||||||
#else
|
|
||||||
_needauthentication = false;
|
|
||||||
#endif // AUTHENTICATION_FEATURE
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESP3DSerialService::initAuthentication() {
|
|
||||||
#if defined(AUTHENTICATION_FEATURE)
|
|
||||||
_auth = ESP3DAuthenticationLevel::guest;
|
|
||||||
#else
|
|
||||||
_auth = ESP3DAuthenticationLevel::admin;
|
|
||||||
#endif // AUTHENTICATION_FEATURE
|
|
||||||
}
|
|
||||||
ESP3DAuthenticationLevel ESP3DSerialService::getAuthentication() {
|
|
||||||
if (_needauthentication) {
|
|
||||||
return _auth;
|
|
||||||
}
|
|
||||||
return ESP3DAuthenticationLevel::admin;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup Serial
|
// Setup Serial
|
||||||
bool ESP3DSerialService::begin(uint8_t serialIndex) {
|
bool ESP3DSerialService::begin(uint8_t serialIndex) {
|
||||||
_serialIndex = serialIndex - 1;
|
_serialIndex = serialIndex - 1;
|
||||||
@ -133,12 +99,21 @@ bool ESP3DSerialService::end() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the array of uint32_t and array size
|
void ESP3DSerialService::flushData(const uint8_t *data, size_t size, ESP3DMessageType type) {
|
||||||
const uint32_t *ESP3DSerialService::get_baudratelist(uint8_t *count) {
|
ESP3DMessage *message = esp3d_message_manager.newMsg(
|
||||||
if (count) {
|
_origin,
|
||||||
*count = sizeof(SupportedBaudList) / sizeof(uint32_t);
|
_id == MAIN_SERIAL ? ESP3DClientType::all_clients
|
||||||
|
: esp3d_commands.getOutputClient(),
|
||||||
|
data, size, getAuthentication());
|
||||||
|
|
||||||
|
if (message) {
|
||||||
|
message->type = type;
|
||||||
|
esp3d_log("Process Message");
|
||||||
|
esp3d_commands.process(message);
|
||||||
|
} else {
|
||||||
|
esp3d_log_e("Cannot create message");
|
||||||
}
|
}
|
||||||
return SupportedBaudList;
|
_lastflush = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function which could be called in other loop
|
// Function which could be called in other loop
|
||||||
@ -165,36 +140,13 @@ void ESP3DSerialService::handle() {
|
|||||||
// we cannot left data in buffer too long
|
// we cannot left data in buffer too long
|
||||||
// in case some commands "forget" to add \n
|
// in case some commands "forget" to add \n
|
||||||
if (((millis() - _lastflush) > TIMEOUT_SERIAL_FLUSH) && (_buffer_size > 0)) {
|
if (((millis() - _lastflush) > TIMEOUT_SERIAL_FLUSH) && (_buffer_size > 0)) {
|
||||||
flushbuffer();
|
flushBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ESP3DSerialService::flushbuffer() {
|
|
||||||
_buffer[_buffer_size] = 0x0;
|
|
||||||
|
|
||||||
// dispatch command
|
|
||||||
if (_started) {
|
|
||||||
ESP3DMessage *message = esp3d_message_manager.newMsg(
|
|
||||||
_origin,
|
|
||||||
_id == MAIN_SERIAL ? ESP3DClientType::all_clients
|
|
||||||
: esp3d_commands.getOutputClient(),
|
|
||||||
(uint8_t *)_buffer, _buffer_size, getAuthentication());
|
|
||||||
if (message) {
|
|
||||||
// process command
|
|
||||||
message->type = ESP3DMessageType::unique;
|
|
||||||
esp3d_commands.process(message);
|
|
||||||
} else {
|
|
||||||
esp3d_log_e("Cannot create message");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_lastflush = millis();
|
|
||||||
_buffer_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// push collected data to buffer and proceed accordingly
|
// push collected data to buffer and proceed accordingly
|
||||||
void ESP3DSerialService::push2buffer(uint8_t *sbuf, size_t len) {
|
void ESP3DSerialService::push2buffer(uint8_t *sbuf, size_t len) {
|
||||||
if (!_started) {
|
if (!_started || !_buffer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
esp3d_log("buffer get %d data ", len);
|
esp3d_log("buffer get %d data ", len);
|
||||||
@ -250,7 +202,7 @@ void ESP3DSerialService::push2buffer(uint8_t *sbuf, size_t len) {
|
|||||||
if (_buffer_size == datalen) {
|
if (_buffer_size == datalen) {
|
||||||
esp3d_log("Flushing buffer");
|
esp3d_log("Flushing buffer");
|
||||||
if (isCommandFrame) {
|
if (isCommandFrame) {
|
||||||
flushbuffer();
|
flushBuffer();
|
||||||
} else {
|
} else {
|
||||||
MKSService::handleFrame(type, (const uint8_t *)_buffer,
|
MKSService::handleFrame(type, (const uint8_t *)_buffer,
|
||||||
_buffer_size);
|
_buffer_size);
|
||||||
@ -294,31 +246,15 @@ void ESP3DSerialService::push2buffer(uint8_t *sbuf, size_t len) {
|
|||||||
#else
|
#else
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
_lastflush = millis();
|
_lastflush = millis();
|
||||||
// command is defined
|
if (esp3d_string::isRealTimeCommand(sbuf[i])) {
|
||||||
if ((char(sbuf[i]) == '\n') || (char(sbuf[i]) == '\r')) {
|
flushChar(sbuf[i]);
|
||||||
if (_buffer_size < ESP3D_SERIAL_BUFFER_SIZE) {
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
|
||||||
_buffer_size++;
|
|
||||||
}
|
|
||||||
flushbuffer();
|
|
||||||
} else if (esp3d_string::isPrintableChar(char(sbuf[i]))) {
|
|
||||||
if (_buffer_size < ESP3D_SERIAL_BUFFER_SIZE) {
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
|
||||||
_buffer_size++;
|
|
||||||
} else {
|
} else {
|
||||||
flushbuffer();
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
_buffer[_buffer_size] = sbuf[i];
|
||||||
_buffer_size++;
|
_buffer_size++;
|
||||||
|
if (_buffer_size > ESP3D_SERIAL_BUFFER_SIZE ||
|
||||||
|
_buffer[_buffer_size - 1] == '\n') {
|
||||||
|
flushBuffer();
|
||||||
}
|
}
|
||||||
} else { // it is not printable char
|
|
||||||
// clean buffer first
|
|
||||||
if (_buffer_size > 0) {
|
|
||||||
flushbuffer();
|
|
||||||
}
|
|
||||||
// process char
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
|
||||||
_buffer_size++;
|
|
||||||
flushbuffer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -331,94 +267,12 @@ bool ESP3DSerialService::reset() {
|
|||||||
ESP_BAUD_RATE, ESP3DSettings::getDefaultIntegerSetting(ESP_BAUD_RATE));
|
ESP_BAUD_RATE, ESP3DSettings::getDefaultIntegerSetting(ESP_BAUD_RATE));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP3DSerialService::updateBaudRate(uint32_t br) {
|
|
||||||
if (br != baudRate()) {
|
|
||||||
Serials[_serialIndex]->flush();
|
|
||||||
Serials[_serialIndex]->updateBaudRate(br);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get current baud rate
|
|
||||||
uint32_t ESP3DSerialService::baudRate() {
|
|
||||||
return Serials[_serialIndex]->baudRate();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ESP3DSerialService::writeBytes(const uint8_t *buffer, size_t size) {
|
|
||||||
if (!_started) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if ((uint)Serials[_serialIndex]->availableForWrite() >= size) {
|
|
||||||
return Serials[_serialIndex]->write(buffer, size);
|
|
||||||
} else {
|
|
||||||
size_t sizetosend = size;
|
|
||||||
size_t sizesent = 0;
|
|
||||||
uint8_t *buffertmp = (uint8_t *)buffer;
|
|
||||||
uint32_t starttime = millis();
|
|
||||||
// loop until all is sent or timeout
|
|
||||||
while (sizetosend > 0 && ((millis() - starttime) < 100)) {
|
|
||||||
size_t available = Serials[_serialIndex]->availableForWrite();
|
|
||||||
if (available > 0) {
|
|
||||||
// in case less is sent
|
|
||||||
available = Serials[_serialIndex]->write(
|
|
||||||
&buffertmp[sizesent],
|
|
||||||
(available >= sizetosend) ? sizetosend : available);
|
|
||||||
sizetosend -= available;
|
|
||||||
sizesent += available;
|
|
||||||
starttime = millis();
|
|
||||||
} else {
|
|
||||||
ESP3DHal::wait(5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sizesent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ESP3DSerialService::readBytes(uint8_t *sbuf, size_t len) {
|
|
||||||
if (!_started) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return Serials[_serialIndex]->readBytes(sbuf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESP3DSerialService::flush() {
|
|
||||||
if (!_started) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Serials[_serialIndex]->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESP3DSerialService::swap() {
|
void ESP3DSerialService::swap() {
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
Serials[_serialIndex]->swap();
|
Serials[_serialIndex]->swap();
|
||||||
#endif // ARDUINO_ARCH_ESP8266
|
#endif // ARDUINO_ARCH_ESP8266
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESP3DSerialService::dispatch(ESP3DMessage *message) {
|
|
||||||
bool done = false;
|
|
||||||
// Only is serial service is started
|
|
||||||
if (_started) {
|
|
||||||
// Only if message is not null
|
|
||||||
if (message) {
|
|
||||||
// if message is not null
|
|
||||||
if (message->data && message->size != 0) {
|
|
||||||
if (writeBytes(message->data, message->size) == message->size) {
|
|
||||||
flush();
|
|
||||||
// Delete message now
|
|
||||||
esp3d_message_manager.deleteMsg(message);
|
|
||||||
done = true;
|
|
||||||
} else {
|
|
||||||
esp3d_log_e("Error while sending data");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
esp3d_log_e("Error null data");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
esp3d_log_e("Error null message");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return done;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // COMMUNICATION_PROTOCOL == MKS_SERIAL || COMMUNICATION_PROTOCOL ==
|
#endif // COMMUNICATION_PROTOCOL == MKS_SERIAL || COMMUNICATION_PROTOCOL ==
|
||||||
// RAW_SERIAL
|
// RAW_SERIAL
|
||||||
#endif // ARDUINO_ARCH_ESP8266
|
#endif // ARDUINO_ARCH_ESP8266
|
@ -99,7 +99,7 @@ size_t Serial_2_Socket::write(const uint8_t *buffer, size_t size) {
|
|||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
_TXbuffer[_TXbufferSize] = buffer[i];
|
_TXbuffer[_TXbufferSize] = buffer[i];
|
||||||
_TXbufferSize++;
|
_TXbufferSize++;
|
||||||
if (buffer[i] == (const uint8_t)'\n' || buffer[i] == (const uint8_t)'\r') {
|
if (buffer[i] == (const uint8_t)'\n') {
|
||||||
esp3d_log("S2S: %s TXSize: %d", (const char *)_TXbuffer, _TXbufferSize);
|
esp3d_log("S2S: %s TXSize: %d", (const char *)_TXbuffer, _TXbufferSize);
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ void Telnet_Server::handle() {
|
|||||||
// we cannot left data in buffer too long
|
// we cannot left data in buffer too long
|
||||||
// in case some commands "forget" to add \n
|
// in case some commands "forget" to add \n
|
||||||
if (((millis() - _lastflush) > TIMEOUT_TELNET_FLUSH) && (_buffer_size > 0)) {
|
if (((millis() - _lastflush) > TIMEOUT_TELNET_FLUSH) && (_buffer_size > 0)) {
|
||||||
flushbuffer();
|
flushBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,57 +214,48 @@ void Telnet_Server::initAuthentication() {
|
|||||||
}
|
}
|
||||||
ESP3DAuthenticationLevel Telnet_Server::getAuthentication() { return _auth; }
|
ESP3DAuthenticationLevel Telnet_Server::getAuthentication() { return _auth; }
|
||||||
|
|
||||||
void Telnet_Server::flushbuffer() {
|
|
||||||
if (!_buffer || !_started) {
|
|
||||||
_buffer_size = 0;
|
void Telnet_Server::flushData(const uint8_t *data, size_t size, ESP3DMessageType type) {
|
||||||
return;
|
ESP3DMessage *message = esp3d_message_manager.newMsg(
|
||||||
}
|
ESP3DClientType::telnet, esp3d_commands.getOutputClient(), data,
|
||||||
_buffer[_buffer_size] = 0x0;
|
size, _auth);
|
||||||
ESP3DMessage *msg = esp3d_message_manager.newMsg(
|
|
||||||
ESP3DClientType::telnet, esp3d_commands.getOutputClient(), _buffer,
|
if (message) {
|
||||||
_buffer_size, _auth);
|
message->type = type;
|
||||||
if (msg) {
|
esp3d_log("Process Message");
|
||||||
// process command
|
esp3d_commands.process(message);
|
||||||
esp3d_commands.process(msg);
|
|
||||||
} else {
|
} else {
|
||||||
esp3d_log_e("Cannot create message");
|
esp3d_log_e("Cannot create message");
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastflush = millis();
|
_lastflush = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Telnet_Server::flushChar(char c) { flushData((uint8_t *)&c, 1, ESP3DMessageType::realtimecmd); }
|
||||||
|
|
||||||
|
void Telnet_Server::flushBuffer() {
|
||||||
|
_buffer[_buffer_size] = 0x0;
|
||||||
|
flushData((uint8_t *)_buffer, _buffer_size, ESP3DMessageType::unique);
|
||||||
_buffer_size = 0;
|
_buffer_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Telnet_Server::push2buffer(uint8_t *sbuf, size_t len) {
|
void Telnet_Server::push2buffer(uint8_t *sbuf, size_t len) {
|
||||||
if (!_buffer) {
|
if (!_buffer || !_started) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
_lastflush = millis();
|
_lastflush = millis();
|
||||||
// command is defined
|
if (esp3d_string::isRealTimeCommand(sbuf[i])) {
|
||||||
if ((char(sbuf[i]) == '\n') || (char(sbuf[i]) == '\r')) {
|
flushChar(sbuf[i]);
|
||||||
if (_buffer_size < ESP3D_TELNET_BUFFER_SIZE) {
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
|
||||||
_buffer_size++;
|
|
||||||
}
|
|
||||||
flushbuffer();
|
|
||||||
} else if (esp3d_string::isPrintableChar(char(sbuf[i]))) {
|
|
||||||
if (_buffer_size < ESP3D_TELNET_BUFFER_SIZE) {
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
|
||||||
_buffer_size++;
|
|
||||||
} else {
|
} else {
|
||||||
flushbuffer();
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
_buffer[_buffer_size] = sbuf[i];
|
||||||
_buffer_size++;
|
_buffer_size++;
|
||||||
|
if (_buffer_size > ESP3D_TELNET_BUFFER_SIZE ||
|
||||||
|
_buffer[_buffer_size - 1] == '\n') {
|
||||||
|
flushBuffer();
|
||||||
}
|
}
|
||||||
} else { // it is not printable char
|
|
||||||
// clean buffer first
|
|
||||||
if (_buffer_size > 0) {
|
|
||||||
flushbuffer();
|
|
||||||
}
|
|
||||||
// process char
|
|
||||||
_buffer[_buffer_size] = sbuf[i];
|
|
||||||
_buffer_size++;
|
|
||||||
flushbuffer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,9 @@ class Telnet_Server {
|
|||||||
uint8_t* _buffer;
|
uint8_t* _buffer;
|
||||||
size_t _buffer_size;
|
size_t _buffer_size;
|
||||||
void push2buffer(uint8_t* sbuf, size_t len);
|
void push2buffer(uint8_t* sbuf, size_t len);
|
||||||
void flushbuffer();
|
void flushBuffer();
|
||||||
|
void flushChar(char c);
|
||||||
|
void flushData(const uint8_t* data, size_t size, ESP3DMessageType type);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Telnet_Server telnet_server;
|
extern Telnet_Server telnet_server;
|
||||||
|
@ -174,15 +174,15 @@ void ESP3DUsbSerialService::receiveCb(const uint8_t *data, size_t data_len,
|
|||||||
}
|
}
|
||||||
if (xSemaphoreTake(_buffer_mutex, portMAX_DELAY) == pdTRUE) {
|
if (xSemaphoreTake(_buffer_mutex, portMAX_DELAY) == pdTRUE) {
|
||||||
for (size_t i = 0; i < data_len; i++) {
|
for (size_t i = 0; i < data_len; i++) {
|
||||||
|
if (esp3d_string::isRealTimeCommand(data[i])) {
|
||||||
|
flushChar(data[i]);
|
||||||
|
} else {
|
||||||
_buffer[_buffer_size] = data[i];
|
_buffer[_buffer_size] = data[i];
|
||||||
_buffer_size++;
|
_buffer_size++;
|
||||||
if (_buffer_size > ESP3D_USB_SERIAL_BUFFER_SIZE ||
|
if (_buffer_size > ESP3D_USB_SERIAL_BUFFER_SIZE ||
|
||||||
_buffer[_buffer_size - 1] == '\n' ||
|
_buffer[_buffer_size - 1] == '\n') {
|
||||||
_buffer[_buffer_size - 1] == '\r') {
|
flushBuffer();
|
||||||
if (_buffer[_buffer_size - 1] == '\r') {
|
|
||||||
_buffer[_buffer_size - 1] = '\n';
|
|
||||||
}
|
}
|
||||||
flushbuffer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xSemaphoreGive(_buffer_mutex);
|
xSemaphoreGive(_buffer_mutex);
|
||||||
@ -397,26 +397,31 @@ void ESP3DUsbSerialService::handle() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP3DUsbSerialService::flushbuffer() {
|
void ESP3DUsbSerialService::flushData(const uint8_t *data, size_t size,
|
||||||
_buffer[_buffer_size] = 0x0;
|
ESP3DMessageType type) {
|
||||||
if (_buffer_size == 1 && _buffer[0] == '\n') {
|
if (!data || !_started) {
|
||||||
_buffer_size = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// dispatch command
|
|
||||||
ESP3DMessage *message = esp3d_message_manager.newMsg(
|
ESP3DMessage *message = esp3d_message_manager.newMsg(
|
||||||
_origin, ESP3DClientType::all_clients, (uint8_t *)_buffer, _buffer_size,
|
_origin, ESP3DClientType::all_clients, data, size, getAuthentication());
|
||||||
getAuthentication());
|
|
||||||
if (message) {
|
if (message) {
|
||||||
// process command
|
// process command
|
||||||
message->type = ESP3DMessageType::unique;
|
message->type = type;
|
||||||
esp3d_log("Message sent to fifo list");
|
esp3d_log("Message sent to fifo list");
|
||||||
_messagesInFIFO.push(message);
|
_messagesInFIFO.push(message);
|
||||||
} else {
|
} else {
|
||||||
esp3d_log_e("Cannot create message");
|
esp3d_log_e("Cannot create message");
|
||||||
}
|
}
|
||||||
_lastflush = millis();
|
_lastflush = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP3DUsbSerialService::flushChar(char c) {
|
||||||
|
flushData((uint8_t *)&c, 1, ESP3DMessageType::realtimecmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP3DUsbSerialService::flushBuffer() {
|
||||||
|
_buffer[_buffer_size] = 0x0;
|
||||||
|
flushData((uint8_t *)_buffer, _buffer_size, ESP3DMessageType::unique);
|
||||||
_buffer_size = 0;
|
_buffer_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,9 @@ class ESP3DUsbSerialService final {
|
|||||||
|
|
||||||
TaskHandle_t _xHandle;
|
TaskHandle_t _xHandle;
|
||||||
ESP3DMessageFIFO _messagesInFIFO;
|
ESP3DMessageFIFO _messagesInFIFO;
|
||||||
void flushbuffer();
|
void flushBuffer();
|
||||||
|
void flushChar(char c);
|
||||||
|
void flushData(const uint8_t* data, size_t size, ESP3DMessageType type);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ESP3DUsbSerialService esp3d_usb_serial_service;
|
extern ESP3DUsbSerialService esp3d_usb_serial_service;
|
||||||
|
@ -281,36 +281,20 @@ size_t WebSocket_Server::writeBytes(const uint8_t *buffer, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WebSocket_Server::push2RXbuffer(uint8_t *sbuf, size_t len) {
|
void WebSocket_Server::push2RXbuffer(uint8_t *sbuf, size_t len) {
|
||||||
if (!_RXbuffer || !_started) {
|
if (!_RXbuffer || !_started || !sbuf) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
_lastRXflush = millis();
|
_lastRXflush = millis();
|
||||||
// command is defined
|
if (esp3d_string::isRealTimeCommand(sbuf[i])) {
|
||||||
if ((char(sbuf[i]) == '\n') || (char(sbuf[i]) == '\r')) {
|
flushRXChar(sbuf[i]);
|
||||||
if (_RXbufferSize < RXBUFFERSIZE) {
|
|
||||||
_RXbuffer[_RXbufferSize] = sbuf[i];
|
|
||||||
_RXbufferSize++;
|
|
||||||
}
|
|
||||||
flushRXbuffer();
|
|
||||||
} else if (esp3d_string::isPrintableChar(char(sbuf[i]))) {
|
|
||||||
if (_RXbufferSize < RXBUFFERSIZE) {
|
|
||||||
_RXbuffer[_RXbufferSize] = sbuf[i];
|
|
||||||
_RXbufferSize++;
|
|
||||||
} else {
|
} else {
|
||||||
flushRXbuffer();
|
|
||||||
_RXbuffer[_RXbufferSize] = sbuf[i];
|
_RXbuffer[_RXbufferSize] = sbuf[i];
|
||||||
_RXbufferSize++;
|
_RXbufferSize++;
|
||||||
}
|
if (_RXbufferSize > RXBUFFERSIZE ||
|
||||||
} else { // it is not printable char
|
_RXbuffer[_RXbufferSize - 1] == '\n') {
|
||||||
// clean buffer first
|
|
||||||
if (_RXbufferSize > 0) {
|
|
||||||
flushRXbuffer();
|
flushRXbuffer();
|
||||||
}
|
}
|
||||||
// process char
|
|
||||||
_RXbuffer[_RXbufferSize] = sbuf[i];
|
|
||||||
_RXbufferSize++;
|
|
||||||
flushRXbuffer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -324,22 +308,33 @@ void WebSocket_Server::initAuthentication() {
|
|||||||
}
|
}
|
||||||
ESP3DAuthenticationLevel WebSocket_Server::getAuthentication() { return _auth; }
|
ESP3DAuthenticationLevel WebSocket_Server::getAuthentication() { return _auth; }
|
||||||
|
|
||||||
|
void WebSocket_Server::flushRXChar(char c) {
|
||||||
|
flushRXData((uint8_t *)&c, 1, ESP3DMessageType::realtimecmd);
|
||||||
|
}
|
||||||
|
|
||||||
void WebSocket_Server::flushRXbuffer() {
|
void WebSocket_Server::flushRXbuffer() {
|
||||||
if (!_RXbuffer || !_started) {
|
_RXbuffer[_RXbufferSize] = 0x0;
|
||||||
|
flushRXData((uint8_t *)_RXbuffer, _RXbufferSize, ESP3DMessageType::unique);
|
||||||
_RXbufferSize = 0;
|
_RXbufferSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocket_Server::flushRXData(const uint8_t *data, size_t size,
|
||||||
|
ESP3DMessageType type) {
|
||||||
|
if (!data || !_started) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_RXbuffer[_RXbufferSize] = 0x0;
|
ESP3DMessage *message = esp3d_message_manager.newMsg(
|
||||||
ESP3DMessage *msg = esp3d_message_manager.newMsg(
|
_type, esp3d_commands.getOutputClient(),
|
||||||
_type, esp3d_commands.getOutputClient(), _RXbuffer, _RXbufferSize, _auth);
|
data, size, _auth);
|
||||||
if (msg) {
|
|
||||||
// process command
|
if (message) {
|
||||||
esp3d_commands.process(msg);
|
message->type = type;
|
||||||
|
esp3d_log("Process Message");
|
||||||
|
esp3d_commands.process(message);
|
||||||
} else {
|
} else {
|
||||||
esp3d_log_e("Cannot create message");
|
esp3d_log_e("Cannot create message");
|
||||||
}
|
}
|
||||||
_lastRXflush = millis();
|
_lastRXflush = millis();
|
||||||
_RXbufferSize = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocket_Server::handle() {
|
void WebSocket_Server::handle() {
|
||||||
|
@ -70,6 +70,8 @@ class WebSocket_Server {
|
|||||||
uint8_t _current_id;
|
uint8_t _current_id;
|
||||||
void flushTXbuffer();
|
void flushTXbuffer();
|
||||||
void flushRXbuffer();
|
void flushRXbuffer();
|
||||||
|
void flushRXChar(char c);
|
||||||
|
void flushRXData(const uint8_t* data, size_t size, ESP3DMessageType type);
|
||||||
uint8_t *_RXbuffer;
|
uint8_t *_RXbuffer;
|
||||||
uint16_t _RXbufferSize;
|
uint16_t _RXbufferSize;
|
||||||
};
|
};
|
||||||
|
@ -5,12 +5,30 @@ import serial.tools.list_ports
|
|||||||
import esp3d_common as common
|
import esp3d_common as common
|
||||||
import marlin
|
import marlin
|
||||||
import grbl
|
import grbl
|
||||||
|
import grblhal
|
||||||
import repetier
|
import repetier
|
||||||
import smoothieware
|
import smoothieware
|
||||||
|
|
||||||
|
def isRealTimeCommand(c: int) -> bool:
|
||||||
|
# Convertit en entier si ce n'est pas déjà le cas
|
||||||
|
if isinstance(c, bytes):
|
||||||
|
c = c[0]
|
||||||
|
elif isinstance(c, str):
|
||||||
|
c = ord(c)
|
||||||
|
|
||||||
|
# Standard characters
|
||||||
|
if c in [ord('?'), ord('!'), ord('~'), 0x18]: # 0x18 is ^X
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Range >= 0x80 et <= 0xA4
|
||||||
|
if 0x80 <= c <= 0xA4:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
print("Please use one of the follwowing FW: marlin, repetier, smoothieware or grbl.")
|
print("Please use one of the follwowing FW: marlin, repetier, smoothieware, grbl or grblhal.")
|
||||||
return
|
return
|
||||||
|
|
||||||
fw_name = sys.argv[1].lower()
|
fw_name = sys.argv[1].lower()
|
||||||
@ -23,41 +41,65 @@ def main():
|
|||||||
fw = smoothieware
|
fw = smoothieware
|
||||||
elif fw_name == "grbl":
|
elif fw_name == "grbl":
|
||||||
fw = grbl
|
fw = grbl
|
||||||
|
elif fw_name == "grblhal":
|
||||||
|
fw = grblhal
|
||||||
else:
|
else:
|
||||||
print("Firmware not supported : {}".format(fw_name))
|
print("Firmware not supported : {}".format(fw_name))
|
||||||
return
|
return
|
||||||
ports = serial.tools.list_ports.comports()
|
ports = serial.tools.list_ports.comports()
|
||||||
portTFT = ""
|
portBoard = ""
|
||||||
print(common.bcolors.COL_GREEN+"Serial ports detected: "+common.bcolors.END_COL)
|
print(common.bcolors.COL_GREEN+"Serial ports detected: "+common.bcolors.END_COL)
|
||||||
for port, desc, hwid in sorted(ports):
|
for port, desc, hwid in sorted(ports):
|
||||||
print(common.bcolors.COL_GREEN+" - {}: {} ".format(port, desc)+common.bcolors.END_COL)
|
print(common.bcolors.COL_GREEN+" - {}: {} ".format(port, desc)+common.bcolors.END_COL)
|
||||||
desc.capitalize()
|
desc.capitalize()
|
||||||
if (desc.find("SERIAL") != -1 or desc.find("UART") != -1):
|
if (desc.find("SERIAL") != -1 or desc.find("UART") != -1):
|
||||||
portTFT = port
|
portBoard = port
|
||||||
print(common.bcolors.COL_GREEN +
|
print(common.bcolors.COL_GREEN +
|
||||||
"Found " + portTFT + " for ESP3D"+common.bcolors.END_COL)
|
"Found " + portBoard + " for ESP3D"+common.bcolors.END_COL)
|
||||||
break
|
break
|
||||||
print(common.bcolors.COL_GREEN+"Open port " + str(port)+common.bcolors.END_COL)
|
print(common.bcolors.COL_GREEN+"Open port " + str(port)+common.bcolors.END_COL)
|
||||||
if (portTFT == ""):
|
if (portBoard == ""):
|
||||||
print(common.bcolors.COL_RED+"No serial port found"+common.bcolors.END_COL)
|
print(common.bcolors.COL_RED+"No serial port found"+common.bcolors.END_COL)
|
||||||
exit(0)
|
exit(0)
|
||||||
ser = serial.Serial(portTFT, 1000000)
|
ser = serial.Serial(portBoard, 115200, timeout=1)
|
||||||
print(common.bcolors.COL_GREEN+"Now Simulating: " + fw_name + common.bcolors.END_COL)
|
print(common.bcolors.COL_GREEN+"Now Simulating: " + fw_name + common.bcolors.END_COL)
|
||||||
starttime = common.current_milli_time()
|
starttime = common.current_milli_time()
|
||||||
# loop forever, just unplug the port to stop the program or do ctrl-c
|
# loop forever, just unplug the port to stop the program or do ctrl-c
|
||||||
|
buffer = bytearray()
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
if ser.in_waiting:
|
if ser.in_waiting:
|
||||||
line = ser.readline().decode('utf-8').strip()
|
# Lire un caractère
|
||||||
|
char = ser.read(1)
|
||||||
|
if not char: # Timeout
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Vérifier si c'est une commande temps réel
|
||||||
|
if isRealTimeCommand(char[0]) and (fw_name == "grbl" or fw_name == "grblhal"):
|
||||||
|
# Traiter immédiatement la commande temps réel
|
||||||
|
cmd = char.decode('utf-8', errors='replace')
|
||||||
|
print(common.bcolors.COL_BLUE + f"RealTime command: {cmd}" + common.bcolors.END_COL)
|
||||||
|
response = fw.processLine(cmd, ser)
|
||||||
|
if response:
|
||||||
|
common.send_echo(ser, response)
|
||||||
|
else:
|
||||||
|
# Ajouter au buffer
|
||||||
|
buffer.extend(char)
|
||||||
|
# Si on trouve une fin de ligne, traiter la ligne
|
||||||
|
if char == b'\n':
|
||||||
|
line = buffer.decode('utf-8').strip()
|
||||||
print(common.bcolors.COL_BLUE + line + common.bcolors.END_COL)
|
print(common.bcolors.COL_BLUE + line + common.bcolors.END_COL)
|
||||||
#ignore log lines from TFT
|
|
||||||
if not line.startswith("["):
|
if not line.startswith("["):
|
||||||
response = fw.processLine(line, ser)
|
response = fw.processLine(line, ser)
|
||||||
if (response != ""):
|
if response:
|
||||||
common.send_echo(ser, response)
|
common.send_echo(ser, response)
|
||||||
|
buffer.clear()
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print(common.bcolors.COL_GREEN+"End of program"+common.bcolors.END_COL)
|
break
|
||||||
exit(0)
|
except Exception as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
|
buffer.clear()
|
||||||
|
|
||||||
|
|
||||||
# call main function
|
# call main function
|
||||||
|
231
tools/fw_simulator/grblhal.py
Normal file
231
tools/fw_simulator/grblhal.py
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# Marlin GCODE parser / responder
|
||||||
|
|
||||||
|
import time
|
||||||
|
import re
|
||||||
|
import random
|
||||||
|
import esp3d_common as common
|
||||||
|
positions = {
|
||||||
|
"X": 0.0,
|
||||||
|
"Y": 0.0,
|
||||||
|
"Z": 0.0,
|
||||||
|
"A": 0.0,
|
||||||
|
"B": 0.0,
|
||||||
|
"C": 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
modes = {
|
||||||
|
"absolute": True
|
||||||
|
}
|
||||||
|
|
||||||
|
report_counter = 0
|
||||||
|
|
||||||
|
|
||||||
|
def wait(durationms, ser):
|
||||||
|
nowtime = common.current_milli_time()
|
||||||
|
while (common.current_milli_time() < nowtime + durationms):
|
||||||
|
if ser.in_waiting:
|
||||||
|
line = ser.readline().decode('utf-8').strip()
|
||||||
|
print(common.bcolors.COL_PURPLE+line+common.bcolors.END_COL)
|
||||||
|
|
||||||
|
|
||||||
|
def ok(line):
|
||||||
|
if (not line.startswith("N")):
|
||||||
|
return "ok (" + line + ")"
|
||||||
|
N = re.findall(r'N\d*', line)
|
||||||
|
if (len(N) > 0):
|
||||||
|
return "ok " + N[0][1:]
|
||||||
|
|
||||||
|
|
||||||
|
# build the response for the busy response,
|
||||||
|
# simulating the delay of the busy response
|
||||||
|
def send_busy(ser, nb):
|
||||||
|
v = nb
|
||||||
|
while (v > 0):
|
||||||
|
# FIXME: the message is not this one on grbl
|
||||||
|
# common.send_echo(ser, "echo:busy: processing")
|
||||||
|
wait(1000, ser)
|
||||||
|
v = v - 1
|
||||||
|
|
||||||
|
# G0/G1 response
|
||||||
|
|
||||||
|
|
||||||
|
def G0_G1_response(cmd, line, ser):
|
||||||
|
global positions
|
||||||
|
X_val = ""
|
||||||
|
Y_val = ""
|
||||||
|
Z_val = ""
|
||||||
|
A_val = ""
|
||||||
|
B_val = ""
|
||||||
|
C_val = ""
|
||||||
|
# extract X
|
||||||
|
X = re.findall(r'X[+]*[-]*\d+[\.]*\d*', cmd)
|
||||||
|
if (len(X) > 0):
|
||||||
|
X_val = X[0][1:]
|
||||||
|
# extract Y
|
||||||
|
Y = re.findall(r'Y[+]*[-]*\d+[\.]*\d*', cmd)
|
||||||
|
if (len(Y) > 0):
|
||||||
|
Y_val = Y[0][1:]
|
||||||
|
# extract Z
|
||||||
|
Z = re.findall(r'Z[+]*[-]*\d+[\.]*\d*', cmd)
|
||||||
|
if (len(Z) > 0):
|
||||||
|
Z_val = Z[0][1:]
|
||||||
|
# extract A
|
||||||
|
A = re.findall(r'A[+]*[-]*\d+[\.]*\d*', cmd)
|
||||||
|
if (len(A) > 0):
|
||||||
|
A_val = A[0][1:]
|
||||||
|
# extract B
|
||||||
|
B = re.findall(r'B[+]*[-]*\d+[\.]*\d*', cmd)
|
||||||
|
if (len(B) > 0):
|
||||||
|
B_val = B[0][1:]
|
||||||
|
# extract C
|
||||||
|
C = re.findall(r'C[+]*[-]*\d+[\.]*\d*', cmd)
|
||||||
|
if (len(C) > 0):
|
||||||
|
C_val = C[0][1:]
|
||||||
|
if (modes["absolute"]):
|
||||||
|
if (X_val != ""):
|
||||||
|
positions["X"] = float(X_val)
|
||||||
|
if (Y_val != ""):
|
||||||
|
positions["Y"] = float(Y_val)
|
||||||
|
if (Z_val != ""):
|
||||||
|
positions["Z"] = float(Z_val)
|
||||||
|
if (A_val!= ""):
|
||||||
|
positions["A"] = float(A_val)
|
||||||
|
if (B_val!= ""):
|
||||||
|
positions["B"] = float(B_val)
|
||||||
|
if (C_val!= ""):
|
||||||
|
positions["C"] = float(C_val)
|
||||||
|
return ok(line)
|
||||||
|
else:
|
||||||
|
if (X_val != ""):
|
||||||
|
positions["X"] += float(X_val)
|
||||||
|
if (Y_val != ""):
|
||||||
|
positions["Y"] += float(Y_val)
|
||||||
|
if (Z_val != ""):
|
||||||
|
positions["Z"] += float(Z_val)
|
||||||
|
if (A_val!= ""):
|
||||||
|
positions["A"] += float(A_val)
|
||||||
|
if (B_val!= ""):
|
||||||
|
positions["B"] += float(B_val)
|
||||||
|
if (C_val!= ""):
|
||||||
|
positions["C"] += float(C_val)
|
||||||
|
return ok(line)
|
||||||
|
|
||||||
|
# $H response
|
||||||
|
|
||||||
|
def Home_response(cmd, line, ser):
|
||||||
|
global positions
|
||||||
|
send_busy(ser, 3)
|
||||||
|
if (cmd.find("X") != -1):
|
||||||
|
positions["X"] = 0.00
|
||||||
|
if (cmd.find("Y") != -1):
|
||||||
|
positions["Y"] = 0.00
|
||||||
|
if (cmd.find("Z") != -1):
|
||||||
|
positions["Z"] = 0.00
|
||||||
|
if (cmd.find("A")!= -1):
|
||||||
|
positions["A"] = 0.00
|
||||||
|
if (cmd.find("B")!= -1):
|
||||||
|
positions["B"] = 0.00
|
||||||
|
if (cmd.find("C")!= -1):
|
||||||
|
positions["C"] = 0.00
|
||||||
|
if (cmd == "G28"):
|
||||||
|
positions["X"] = 0.00
|
||||||
|
positions["Y"] = 0.00
|
||||||
|
positions["Z"] = 0.00
|
||||||
|
positions["A"] = 0.00
|
||||||
|
positiones["B"] = 0.00
|
||||||
|
positions["C"] = 0.00
|
||||||
|
return ok(line)
|
||||||
|
|
||||||
|
|
||||||
|
# Absolute mode
|
||||||
|
|
||||||
|
|
||||||
|
def G90_response(cmd, line, ser):
|
||||||
|
global modes
|
||||||
|
modes["absolute"] = True
|
||||||
|
return ok(line)
|
||||||
|
|
||||||
|
# Relative mode
|
||||||
|
|
||||||
|
|
||||||
|
def G91_response(cmd, line, ser):
|
||||||
|
global modes
|
||||||
|
modes["absolute"] = False
|
||||||
|
return ok(line)
|
||||||
|
|
||||||
|
def Jog_response(cmd, line, ser):
|
||||||
|
if (cmd.find("G91")!= -1):
|
||||||
|
G91_response(cmd, line, ser)
|
||||||
|
elif (cmd.find("G90")!= -1):
|
||||||
|
G90_response(cmd, line, ser)
|
||||||
|
cmd = cmd.replace("G90", "")
|
||||||
|
cmd = cmd.replace("G91", "")
|
||||||
|
cmd = cmd.replace("G21", "")
|
||||||
|
cmd = cmd.strip()
|
||||||
|
return G0_G1_response(cmd, line, ser)
|
||||||
|
|
||||||
|
# status response
|
||||||
|
# "<Idle|MPos:0.000,0.000,0.000,1.000,1.000|FS:0,0|WCO:0.000,0.000,0.000,1.000,1.000>\n"
|
||||||
|
# "<Idle|MPos:0.000,0.000,0.000,1.000,1.000|FS:0,0|A:S|Pn:P>\n"
|
||||||
|
# "<Idle|MPos:0.000,0.000,0.000,1.000,1.000|FS:0,0|Ov:100,100,100|Pn:XYZ>\n"
|
||||||
|
def status_response(cmd, line, ser):
|
||||||
|
global positions
|
||||||
|
global report_counter
|
||||||
|
wpco = ""
|
||||||
|
ov = ""
|
||||||
|
fs = "|FS:0,0"
|
||||||
|
astate = ""
|
||||||
|
pn = ""
|
||||||
|
status = "Idle"
|
||||||
|
report_counter += 1
|
||||||
|
if report_counter == 11:
|
||||||
|
report_counter = 1
|
||||||
|
if report_counter == 1:
|
||||||
|
wpco = "|WCO:0.000,0.000,0.000,1.000,1.000,1.000"
|
||||||
|
if report_counter == 2:
|
||||||
|
#FIXME: use variable to report the override values
|
||||||
|
ov = "|Ov:100,100,100"
|
||||||
|
pn = "|Pn:XYZ"
|
||||||
|
if report_counter >= 3:
|
||||||
|
astate = "|A:S"
|
||||||
|
pn = "|Pn:P"
|
||||||
|
|
||||||
|
position = "|MPos:" + "{:.3f}".format(positions["X"]) + "," + "{:.3f}".format(
|
||||||
|
positions["Y"]) + "," + "{:.3f}".format(positions["Z"]) + "," + "{:.3f}".format(positions["A"]) + "," + "{:.3f}".format(positions["B"]) + "," + "{:.3f}".format(positions["C"])
|
||||||
|
return "<" + status + position + fs + wpco + ov + astate + pn + ">\n"
|
||||||
|
|
||||||
|
|
||||||
|
# List of supported methods
|
||||||
|
methods = [
|
||||||
|
{"str": "G0", "fn": G0_G1_response},
|
||||||
|
{"str": "G1", "fn": G0_G1_response},
|
||||||
|
{"str": "$H", "fn": Home_response},
|
||||||
|
{"str": "$J=", "fn": Jog_response},
|
||||||
|
{"str": "G90", "fn": G90_response},
|
||||||
|
{"str": "G91", "fn": G91_response},
|
||||||
|
{"str": "?", "fn": status_response},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Process a line of GCODE
|
||||||
|
def processLine(line, ser):
|
||||||
|
time.sleep(0.01)
|
||||||
|
cmd = line
|
||||||
|
if (line.startswith("N")):
|
||||||
|
p = line.find(' ')
|
||||||
|
cmd = line[p+1:]
|
||||||
|
p = cmd.rfind('*')
|
||||||
|
cmd = cmd[:p]
|
||||||
|
global methods
|
||||||
|
for method in methods:
|
||||||
|
if cmd.startswith(method["str"]):
|
||||||
|
return method["fn"](cmd, line, ser)
|
||||||
|
if line.startswith("M") or line.startswith("G") or line.startswith("N") or line.startswith("$"):
|
||||||
|
return ok(line)
|
||||||
|
if line.find("[esp") != -1 or line.find("[0;") != -1 or line.find("[1;") != -1:
|
||||||
|
return ""
|
||||||
|
if line.startswith("ESP-ROM") or line.startswith("Build:") or line.startswith("SPIWP:") or line.startswith("mode:")or line.startswith("load:") or line.startswith("entry "):
|
||||||
|
return ""
|
||||||
|
#FIXME: this is not grbl response if the command is not recognized
|
||||||
|
return "echo:Unknown command: \"" + line + "\"\nok"
|
33
tools/serial_test/serial_test.py
Normal file
33
tools/serial_test/serial_test.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import serial
|
||||||
|
import time
|
||||||
|
|
||||||
|
# Configuration du port série
|
||||||
|
ser = serial.Serial(
|
||||||
|
port='COM4', # Port série Windows
|
||||||
|
baudrate=115200, # Vitesse en bauds
|
||||||
|
timeout=1 # Timeout en secondes
|
||||||
|
)
|
||||||
|
|
||||||
|
def format_char(c):
|
||||||
|
# Convertit un caractère en sa représentation lisible
|
||||||
|
if c == b'\r':
|
||||||
|
return '\\r'
|
||||||
|
elif c == b'\n':
|
||||||
|
return '\\n'
|
||||||
|
else:
|
||||||
|
return f"{c.decode('ascii', errors='replace')}({ord(c)})"
|
||||||
|
|
||||||
|
try:
|
||||||
|
print("Lecture du port série COM4. Ctrl+C pour arrêter.")
|
||||||
|
while True:
|
||||||
|
if ser.in_waiting > 0:
|
||||||
|
# Lire un caractère à la fois
|
||||||
|
char = ser.read(1)
|
||||||
|
print(format_char(char), end=' ', flush=True)
|
||||||
|
time.sleep(0.01) # Petit délai pour ne pas surcharger le CPU
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\nArrêt du programme")
|
||||||
|
finally:
|
||||||
|
ser.close()
|
||||||
|
print("Port série fermé")
|
Loading…
x
Reference in New Issue
Block a user