mirror of
https://git.mirrors.martin98.com/https://github.com/luc-github/ESP3D.git
synced 2025-07-28 02:31:59 +08:00

* Update WebSocket library * Update SSDP library * Update TFT_eSPI library * Update EspLuaEngine library * Update SDFat library * Change to pioarduino * Make ESP3DMessageFIFO and ESP3DMessage more thread safe * Fix sanity checks for BT * Add some C6 support * Refactor ethernet code * Split Ethernet Sta / WiFi sta ESP Commands and settings * Simplify wait and wdtFeed code * Set C3 with 4MB by default in platformio.ini * Apply Disable brown out only on ESP32 to avoid crash e.g:ESP32S3 * Add missing entries in platformio.ini
1646 lines
50 KiB
C++
1646 lines
50 KiB
C++
/*
|
|
commands.cpp - ESP3D commands 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
|
|
*/
|
|
// #define ESP_LOG_FEATURE LOG_OUTPUT_SERIAL0
|
|
#include "esp3d_commands.h"
|
|
|
|
#include "../include/esp3d_config.h"
|
|
#include "esp3d.h"
|
|
#include "esp3d_settings.h"
|
|
|
|
#if defined(ESP_LOG_FEATURE)
|
|
const char *esp3dclientstr[] = {
|
|
"no_client", "serial", "usb_serial", "stream",
|
|
"telnet", "http", "webui_websocket", "websocket",
|
|
"rendering", "bluetooth", "socket_serial", "echo_serial",
|
|
"serial_bridge", "remote_screen", "mks_serial", "command",
|
|
"system", "all_clients"};
|
|
#define GETCLIENTSTR(id) \
|
|
static_cast<uint8_t>(id) >= 0 && \
|
|
static_cast<uint8_t>(id) <= \
|
|
static_cast<uint8_t>(ESP3DClientType::all_clients) \
|
|
? esp3dclientstr[static_cast<uint8_t>(id)] \
|
|
: "Out of index"
|
|
|
|
const char *esp3dmsgstr[] = {"head", "core", "tail", "unique"};
|
|
#define GETMSGTYPESTR(id) \
|
|
static_cast<uint8_t>(id) >= 0 && \
|
|
static_cast<uint8_t>(id) <= \
|
|
static_cast<uint8_t>(ESP3DMessageType::unique) \
|
|
? esp3dmsgstr[static_cast<uint8_t>(id)] \
|
|
: "Out of index"
|
|
|
|
#endif // defined(ESP_LOG_FEATURE)
|
|
|
|
#if COMMUNICATION_PROTOCOL == MKS_SERIAL
|
|
#include "../modules/mks/mks_service.h"
|
|
#endif // COMMUNICATION_PROTOCOL == MKS_SERIAL
|
|
|
|
#include "../modules/serial/serial_service.h"
|
|
|
|
#if defined(TELNET_FEATURE)
|
|
#include "../modules/telnet/telnet_server.h"
|
|
#endif // TELNET_FEATURE
|
|
|
|
#if defined(HTTP_FEATURE) || defined(WS_DATA_FEATURE)
|
|
#include "../modules/websocket/websocket_server.h"
|
|
#endif // HTTP_FEATURE || WS_DATA_FEATURE
|
|
|
|
#if defined(HTTP_FEATURE)
|
|
#include "../modules/http/http_server.h"
|
|
#endif // HTTP_FEATURE
|
|
|
|
#if defined(ESP_LUA_INTERPRETER_FEATURE)
|
|
#include "../modules/lua_interpreter/lua_interpreter_service.h"
|
|
#endif // ESP_LUA_INTERPRETER_FEATURE
|
|
|
|
#ifdef BLUETOOTH_FEATURE
|
|
#include "../modules/bluetooth/BT_service.h"
|
|
#endif // BLUETOOTH_FEATURE
|
|
|
|
#if defined(ESP3DLIB_ENV) && COMMUNICATION_PROTOCOL == SOCKET_SERIAL
|
|
#include "../modules/serial2socket/serial2socket.h"
|
|
#endif // defined(ESP3DLIB_ENV) && COMMUNICATION_PROTOCOL == SOCKET_SERIAL
|
|
|
|
#if defined(DISPLAY_DEVICE)
|
|
#include "../modules/display/display.h"
|
|
#endif // DISPLAY_DEVICE
|
|
|
|
ESP3DCommands esp3d_commands;
|
|
|
|
ESP3DCommands::ESP3DCommands() {
|
|
#if COMMUNICATION_PROTOCOL == RAW_SERIAL
|
|
_output_client = ESP3DClientType::serial;
|
|
#endif // COMMUNICATION_PROTOCOL == RAW_SERIAL
|
|
#if COMMUNICATION_PROTOCOL == MKS_SERIAL
|
|
_output_client = ESP3DClientType::mks_serial;
|
|
#endif // COMMUNICATION_PROTOCOL == MKS_SERIAL
|
|
#if COMMUNICATION_PROTOCOL == SOCKET_SERIAL
|
|
_output_client = ESP3DClientType::socket_serial;
|
|
#endif //
|
|
}
|
|
|
|
ESP3DCommands::~ESP3DCommands() {}
|
|
|
|
bool ESP3DCommands::isRealTimeCommand(char *cmd, size_t len) { return false; }
|
|
|
|
// check if current line is an [ESPXXX] command
|
|
bool ESP3DCommands::is_esp_command(uint8_t *sbuf, size_t len) {
|
|
// TODO
|
|
// M117 should be handled here and transfered to [ESP214] if it is an host
|
|
if (len < 5) {
|
|
return false;
|
|
}
|
|
if ((char(sbuf[0]) == '[') && (char(sbuf[1]) == 'E') &&
|
|
(char(sbuf[2]) == 'S') && (char(sbuf[3]) == 'P') &&
|
|
((char(sbuf[4]) == ']') || (char(sbuf[5]) == ']') ||
|
|
(char(sbuf[6]) == ']') || (char(sbuf[7]) == ']'))) {
|
|
return true;
|
|
}
|
|
// echo command header on some targeted firmware
|
|
if (len >= 14) {
|
|
if ((char(sbuf[0]) == 'e') && (char(sbuf[1]) == 'c') &&
|
|
(char(sbuf[2]) == 'h') && (char(sbuf[3]) == 'o') &&
|
|
(char(sbuf[4]) == ':') && (char(sbuf[5]) == ' ') &&
|
|
(char(sbuf[6]) == '[') && (char(sbuf[7]) == 'E') &&
|
|
(char(sbuf[8]) == 'S') && (char(sbuf[9]) == 'P') &&
|
|
((char(sbuf[4]) == ']') || (char(sbuf[5]) == ']') ||
|
|
(char(sbuf[6]) == ']') || (char(sbuf[7]) == ']'))) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const char *ESP3DCommands::format_response(uint cmdID, bool isjson, bool isok,
|
|
const char *message) {
|
|
static String res;
|
|
res = "";
|
|
if (!isjson) {
|
|
res += message;
|
|
} else {
|
|
res = "{\"cmd\":\"";
|
|
res += String(cmdID);
|
|
res += "\",\"status\":\"";
|
|
if (isok) {
|
|
res += "ok";
|
|
} else {
|
|
res += "error";
|
|
}
|
|
res += "\",\"data\":";
|
|
if (message[0] != '{') {
|
|
res += "\"";
|
|
}
|
|
res += message;
|
|
if (message[0] != '{') {
|
|
res += "\"";
|
|
}
|
|
res += "}";
|
|
}
|
|
return res.c_str();
|
|
}
|
|
|
|
bool ESP3DCommands::hasTag(ESP3DMessage *msg, uint start, const char *label) {
|
|
if (!msg) {
|
|
esp3d_log_e("no msg for tag %s", label);
|
|
return false;
|
|
}
|
|
String lbl = label;
|
|
// esp3d_log("checking message for tag %s", label);
|
|
uint lenLabel = strlen(label);
|
|
lbl += "=";
|
|
lbl = get_param(msg, start, lbl.c_str());
|
|
if (lbl.length() != 0) {
|
|
// esp3d_log("Label is used with parameter %s", lbl.c_str());
|
|
// make result uppercase
|
|
lbl.toUpperCase();
|
|
return (lbl == "YES" || lbl == "1" || lbl == "TRUE");
|
|
}
|
|
bool prevCharIsEscaped = false;
|
|
bool prevCharIsspace = true;
|
|
// esp3d_log("Checking label as tag");
|
|
for (uint i = start; i < msg->size; i++) {
|
|
char c = char(msg->data[i]);
|
|
// esp3d_log("%c", c);
|
|
if (c == label[0] && prevCharIsspace) {
|
|
uint p = 0;
|
|
while (i < msg->size && p < lenLabel && c == label[p]) {
|
|
i++;
|
|
p++;
|
|
if (i < msg->size) {
|
|
c = char(msg->data[i]);
|
|
// esp3d_log("%c vs %c", c, char(msg->data[i]));
|
|
}
|
|
}
|
|
if (p == lenLabel) {
|
|
// end of params
|
|
if (i == msg->size || std::isspace(c)) {
|
|
// esp3d_log("label %s found", label);
|
|
return true;
|
|
}
|
|
}
|
|
if (std::isspace(c) && !prevCharIsEscaped) {
|
|
prevCharIsspace = true;
|
|
}
|
|
if (c == '\\') {
|
|
prevCharIsEscaped = true;
|
|
} else {
|
|
prevCharIsEscaped = false;
|
|
}
|
|
}
|
|
}
|
|
// esp3d_log("label %s not found", label);
|
|
return false;
|
|
}
|
|
|
|
const char *ESP3DCommands::get_param(ESP3DMessage *msg, uint start,
|
|
const char *label, bool *found) {
|
|
if (!msg) {
|
|
esp3d_log_e("no message");
|
|
return "";
|
|
}
|
|
return get_param((const char *)msg->data, msg->size, start, label, found);
|
|
}
|
|
|
|
const char *ESP3DCommands::get_param(const char *data, uint size, uint start,
|
|
const char *label, bool *found) {
|
|
esp3d_log("get_param %s", label);
|
|
int startPos = -1;
|
|
uint lenLabel = strlen(label);
|
|
static String value;
|
|
bool prevCharIsEscaped = false;
|
|
bool prevCharIsspace = true;
|
|
value = "";
|
|
uint startp = start;
|
|
if (found) {
|
|
*found = false;
|
|
}
|
|
while (char(data[startp]) == ' ' && startp < size) {
|
|
startp++;
|
|
}
|
|
for (uint i = startp; i < size; i++) {
|
|
char c = char(data[i]);
|
|
if (c == label[0] && startPos == -1 && prevCharIsspace) {
|
|
uint p = 0;
|
|
while (i < size && p < lenLabel && c == label[p]) {
|
|
i++;
|
|
p++;
|
|
if (i < size) {
|
|
c = char(data[i]);
|
|
}
|
|
}
|
|
if (p == lenLabel) {
|
|
startPos = i;
|
|
if (found) {
|
|
*found = true;
|
|
}
|
|
}
|
|
}
|
|
if (std::isspace(c) && !prevCharIsEscaped) {
|
|
prevCharIsspace = true;
|
|
}
|
|
if (startPos > -1 && i < size) {
|
|
if (c == '\\') {
|
|
prevCharIsEscaped = true;
|
|
}
|
|
if (std::isspace(c) && !prevCharIsEscaped) {
|
|
return value.c_str();
|
|
}
|
|
|
|
if (c != '\\') {
|
|
value += c;
|
|
prevCharIsEscaped = false;
|
|
}
|
|
}
|
|
}
|
|
esp3d_log("found *%s*", value.c_str());
|
|
return value.c_str();
|
|
}
|
|
|
|
const char *ESP3DCommands::get_clean_param(ESP3DMessage *msg, uint start) {
|
|
if (!msg) {
|
|
esp3d_log_e("no message");
|
|
return "";
|
|
}
|
|
static String value;
|
|
bool prevCharIsEscaped = false;
|
|
uint startp = start;
|
|
while (char(msg->data[startp]) == ' ' && startp < msg->size) {
|
|
startp++;
|
|
}
|
|
value = "";
|
|
for (uint i = startp; i < msg->size; i++) {
|
|
char c = char(msg->data[i]);
|
|
if (c == '\\') {
|
|
prevCharIsEscaped = true;
|
|
}
|
|
if (std::isspace(c) && !prevCharIsEscaped) {
|
|
esp3d_log("testing *%s*", value.c_str());
|
|
if (value == "json" || value.startsWith("json=") ||
|
|
value.startsWith("pwd=")) {
|
|
esp3d_log("clearing *%s*", value.c_str());
|
|
value = "";
|
|
} else {
|
|
esp3d_log("returning *%s*", value.c_str());
|
|
return value.c_str();
|
|
}
|
|
}
|
|
if (c != '\\') {
|
|
if ((std::isspace(c) && prevCharIsEscaped) || !std::isspace(c)) {
|
|
value += c;
|
|
}
|
|
prevCharIsEscaped = false;
|
|
}
|
|
}
|
|
esp3d_log("testing *%s*", value.c_str());
|
|
// for empty value
|
|
if (value == "json" || value.startsWith("json=") ||
|
|
value.startsWith("pwd=")) {
|
|
esp3d_log("clearing *%s*", value.c_str());
|
|
value = "";
|
|
}
|
|
esp3d_log("returning *%s*", value.c_str());
|
|
return value.c_str();
|
|
}
|
|
|
|
bool ESP3DCommands::has_param(ESP3DMessage *msg, uint start) {
|
|
return strlen(get_clean_param(msg, start)) != 0;
|
|
}
|
|
|
|
void ESP3DCommands::execute_internal_command(int cmd, int cmd_params_pos,
|
|
ESP3DMessage *msg) {
|
|
if (!msg) {
|
|
esp3d_log_e("no msg for cmd %d", cmd);
|
|
return;
|
|
}
|
|
#ifdef AUTHENTICATION_FEATURE
|
|
String pwd = get_param(msg, cmd_params_pos, "pwd=");
|
|
if (pwd.length() != 0 && (msg->origin == ESP3DClientType::serial ||
|
|
msg->origin == ESP3DClientType::serial_bridge ||
|
|
msg->origin == ESP3DClientType::telnet ||
|
|
msg->origin == ESP3DClientType::websocket ||
|
|
msg->origin == ESP3DClientType::bluetooth)) {
|
|
msg->authentication_level =
|
|
AuthenticationService::getAuthenticatedLevel(pwd.c_str(), msg);
|
|
// update authentication level for current client
|
|
switch (msg->origin) {
|
|
case ESP3DClientType::serial:
|
|
esp3d_serial_service.setAuthentication(msg->authentication_level);
|
|
break;
|
|
#if defined(ESP_SERIAL_BRIDGE_OUTPUT)
|
|
case ESP3DClientType::serial_bridge:
|
|
serial_bridge_service.setAuthentication(msg->authentication_level);
|
|
break;
|
|
#endif // ESP_SERIAL_BRIDGE_OUTPUT
|
|
#if defined(TELNET_FEATURE)
|
|
case ESP3DClientType::telnet:
|
|
telnet_server.setAuthentication(msg->authentication_level);
|
|
break;
|
|
#endif // TELNET_FEATURE
|
|
#if defined(WS_DATA_FEATURE)
|
|
case ESP3DClientType::websocket:
|
|
websocket_data_server.setAuthentication(msg->authentication_level);
|
|
break;
|
|
#endif // WS_DATA_FEATURE
|
|
#ifdef BLUETOOTH_FEATURE
|
|
case ESP3DClientType::bluetooth:
|
|
bt_service.setAuthentication(msg->authentication_level);
|
|
break;
|
|
#endif // BLUETOOTH_FEATURE
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endif // AUTHENTICATION_FEATURE
|
|
switch (cmd) {
|
|
// ESP3D Help
|
|
//[ESP0] or [ESP]
|
|
case 0:
|
|
ESP0(cmd_params_pos, msg);
|
|
break;
|
|
|
|
#if defined(WIFI_FEATURE)
|
|
// STA SSID
|
|
//[ESP100]<SSID>[pwd=<admin password>]
|
|
case 100:
|
|
ESP100(cmd_params_pos, msg);
|
|
break;
|
|
// STA Password
|
|
//[ESP101]<Password>[pwd=<admin password>]
|
|
case 101:
|
|
ESP101(cmd_params_pos, msg);
|
|
break;
|
|
#endif // WIFI_FEATURE
|
|
#if defined(WIFI_FEATURE)
|
|
// Change STA IP mode (DHCP/STATIC)
|
|
//[ESP102]<mode>pwd=<admin password>
|
|
case 102:
|
|
ESP102(cmd_params_pos, msg);
|
|
break;
|
|
// Change STA IP/Mask/GW
|
|
//[ESP103]IP=<IP> MSK=<IP> GW=<IP> pwd=<admin password>
|
|
case 103:
|
|
ESP103(cmd_params_pos, msg);
|
|
break;
|
|
// Set fallback mode which can be BT, WIFI-AP, OFF
|
|
//[ESP104]<state>pwd=<admin password>
|
|
case 104:
|
|
ESP104(cmd_params_pos, msg);
|
|
break;
|
|
// AP SSID
|
|
//[ESP105]<SSID>[pwd=<admin password>]
|
|
case 105:
|
|
ESP105(cmd_params_pos, msg);
|
|
break;
|
|
// AP Password
|
|
//[ESP106]<Password>[pwd=<admin password>]
|
|
case 106:
|
|
ESP106(cmd_params_pos, msg);
|
|
break;
|
|
// Change AP IP
|
|
//[ESP107]<IP> pwd=<admin password>
|
|
case 107:
|
|
ESP107(cmd_params_pos, msg);
|
|
break;
|
|
// Change AP channel
|
|
//[ESP108]<channel>pwd=<admin password>
|
|
case 108:
|
|
ESP108(cmd_params_pos, msg);
|
|
break;
|
|
#endif // WIFI_FEATURE
|
|
|
|
#if defined(WIFI_FEATURE) || defined(BLUETOOTH_FEATURE) || defined(ETH_FEATURE)
|
|
// Set radio state at boot which can be BT, WIFI-STA, WIFI-AP, ETH-STA,
|
|
// OFF
|
|
//[ESP110]<state>pwd=<admin password>
|
|
case 110:
|
|
ESP110(cmd_params_pos, msg);
|
|
break;
|
|
#endif // WIFI_FEATURE || BLUETOOTH_FEATURE || ETH_FEATURE)
|
|
|
|
#if defined(WIFI_FEATURE) || defined(ETH_FEATURE)
|
|
// Get current IP
|
|
//[ESP111]
|
|
case 111:
|
|
ESP111(cmd_params_pos, msg);
|
|
break;
|
|
#endif // WIFI_FEATURE || ETH_FEATURE)
|
|
|
|
#if defined(WIFI_FEATURE) || defined(ETH_FEATURE) || defined(BT_FEATURE)
|
|
// Get/Set hostname
|
|
//[ESP112]<Hostname> pwd=<admin password>
|
|
case 112:
|
|
ESP112(cmd_params_pos, msg);
|
|
break;
|
|
// Get/Set boot Network (WiFi/BT/Ethernet) state which can be ON, OFF
|
|
//[ESP114]<state>pwd=<admin password>
|
|
case 114:
|
|
ESP114(cmd_params_pos, msg);
|
|
break;
|
|
// Get/Set immediate Network (WiFi/BT/Ethernet) state which can be ON, OFF
|
|
//[ESP115]<state>pwd=<admin password>
|
|
case 115:
|
|
ESP115(cmd_params_pos, msg);
|
|
break;
|
|
#endif // WIFI_FEATURE|| ETH_FEATURE || BT_FEATURE
|
|
|
|
#if defined(ETH_FEATURE)
|
|
// Change ETH STA IP mode (DHCP/STATIC)
|
|
//[ESP116]<mode>pwd=<admin password>
|
|
case 116:
|
|
ESP102(cmd_params_pos, msg);
|
|
break;
|
|
// Change ETH STA IP/Mask/GW
|
|
//[ESP117]IP=<IP> MSK=<IP> GW=<IP> pwd=<admin password>
|
|
case 117:
|
|
ESP117(cmd_params_pos, msg);
|
|
break;
|
|
// Set fallback mode which can be BT, OFF
|
|
//[ESP118]<state>pwd=<admin password>
|
|
case 118:
|
|
ESP118(cmd_params_pos, msg);
|
|
break;
|
|
#endif // ETH_FEATURE
|
|
|
|
#ifdef HTTP_FEATURE
|
|
// Set HTTP state which can be ON, OFF
|
|
//[ESP120]<state>pwd=<admin password>
|
|
case 120:
|
|
ESP120(cmd_params_pos, msg);
|
|
break;
|
|
// Set HTTP port
|
|
//[ESP121]<port>pwd=<admin password>
|
|
case 121:
|
|
ESP121(cmd_params_pos, msg);
|
|
break;
|
|
#endif // HTTP_FEATURE
|
|
#ifdef TELNET_FEATURE
|
|
// Set TELNET state which can be ON, OFF
|
|
//[ESP130]<state>pwd=<admin password>
|
|
case 130:
|
|
ESP130(cmd_params_pos, msg);
|
|
break;
|
|
// Set TELNET port
|
|
//[ESP131]<port>pwd=<admin password>
|
|
case 131:
|
|
ESP131(cmd_params_pos, msg);
|
|
break;
|
|
#endif // TELNET_FEATURE
|
|
#ifdef TIMESTAMP_FEATURE
|
|
// Sync / Set / Get current time
|
|
//[ESP140]<SYNC> <srv1=XXXXX> <srv2=XXXXX> <srv3=XXXXX> <zone=xxx>
|
|
//<dst=YES/NO> <time=YYYY-MM-DD#H24:MM:SS> pwd=<admin password>
|
|
case 140:
|
|
ESP140(cmd_params_pos, msg);
|
|
break;
|
|
#endif // TIMESTAMP_FEATURE
|
|
// Get/Set display/set boot delay in ms / Verbose boot
|
|
//[ESP150]<delay=time in
|
|
// milliseconds><verbose=YES/NO>pwd=<admin password>
|
|
case 150:
|
|
ESP150(cmd_params_pos, msg);
|
|
break;
|
|
#ifdef WS_DATA_FEATURE
|
|
// Set WebSocket state which can be ON, OFF
|
|
//[ESP160]<state>pwd=<admin password>
|
|
case 160:
|
|
ESP160(cmd_params_pos, msg);
|
|
break;
|
|
// Set WebSocket port
|
|
//[ESP161]<port>pwd=<admin password>
|
|
case 161:
|
|
ESP161(cmd_params_pos, msg);
|
|
break;
|
|
#endif // WS_DATA_FEATURE
|
|
#ifdef CAMERA_DEVICE
|
|
// Get/Set Camera command value / list all values in JSON/plain
|
|
//[ESP170]label=<value> pwd=<admin/user password>
|
|
// label can be:
|
|
// light / framesize / quality / contrast / brightness / saturation /
|
|
// gainceiling / colorbar / awb / agc / aec / hmirror / vflip /
|
|
// awb_gain / agc_gain / aec_value / aec2 / cw / bpc / wpc / raw_gma /
|
|
// lenc / special_effect / wb_mode / ae_level
|
|
case 170:
|
|
ESP170(cmd_params_pos, msg);
|
|
break;
|
|
// Save frame to target path and filename (default target = todaydate,
|
|
// default name=timestamp.jpg) [ESP171]path=<target path>
|
|
// filename = < target
|
|
// filename> pwd=<admin/user password>
|
|
case 171:
|
|
ESP171(cmd_params_pos, msg);
|
|
break;
|
|
#endif // CAMERA_DEVICE
|
|
#ifdef FTP_FEATURE
|
|
// Set Ftp state which can be ON, OFF
|
|
//[ESP180]<state>pwd=<admin password>
|
|
case 180:
|
|
ESP180(cmd_params_pos, msg);
|
|
break;
|
|
// Set/get ftp ports
|
|
//[ESP181]ctrl=<port> active=<port> passive=<port> pwd=<admin password >
|
|
// case 181:
|
|
ESP181(cmd_params_pos, msg);
|
|
break;
|
|
#endif // FTP_FEATURE
|
|
#ifdef WEBDAV_FEATURE
|
|
// Set webdav state which can be ON, OFF
|
|
//[ESP190]<state>pwd=<admin password>
|
|
case 190:
|
|
ESP190(cmd_params_pos, msg);
|
|
break;
|
|
// Set/get webdav port
|
|
//[ESP191]ctrl=<port> active=<port> passive=<port> pwd=<admin password >
|
|
// case 191:
|
|
ESP191(cmd_params_pos, msg);
|
|
break;
|
|
#endif // WEBDAV_FEATURE
|
|
#if defined(SD_DEVICE)
|
|
// Get/Set SD Card Status
|
|
//[ESP200] json=<YES/NO> <RELEASESD> <REFRESH> pwd=<user/admin password >
|
|
case 200:
|
|
ESP200(cmd_params_pos, msg);
|
|
break;
|
|
#if SD_DEVICE != ESP_SDIO
|
|
// Get/Set SD card Speed factor 1 2 4 6 8 16 32
|
|
//[ESP202]SPEED=<value>pwd=<user/admin password>
|
|
case 202:
|
|
ESP202(cmd_params_pos, msg);
|
|
break;
|
|
#endif // SD_DEVICE != ESP_SDIO
|
|
#ifdef SD_UPDATE_FEATURE
|
|
// Get/Set SD Check at boot state which can be ON, OFF
|
|
//[ESP402]<state>pwd=<admin password>
|
|
case 402:
|
|
ESP402(cmd_params_pos, msg);
|
|
break;
|
|
#endif // #ifdef SD_UPDATE_FEATURE
|
|
#endif // SD_DEVICE
|
|
#ifdef DIRECT_PIN_FEATURE
|
|
// Get/Set pin value
|
|
//[ESP201]P<pin> V<value> [PULLUP=YES RAW=YES]pwd=<admin password>
|
|
case 201:
|
|
ESP201(cmd_params_pos, msg);
|
|
break;
|
|
#endif // DIRECT_PIN_FEATURE
|
|
#ifdef SENSOR_DEVICE
|
|
// Get SENSOR Value / type/Set SENSOR type
|
|
//[ESP210] <TYPE> <type=NONE/xxx> <interval=XXX in millisec>
|
|
case 210:
|
|
ESP210(cmd_params_pos, msg);
|
|
break;
|
|
#endif // #ifdef SENSOR_DEVICE
|
|
#if defined(PRINTER_HAS_DISPLAY)
|
|
// Output to printer screen status
|
|
//[ESP212]<Text>json=<no> pwd=<user/admin password>
|
|
case 212:
|
|
ESP212(cmd_params_pos, msg);
|
|
break;
|
|
#endif // PRINTER_HAS_DISPLAY
|
|
#if defined(DISPLAY_DEVICE)
|
|
// Output to esp screen status
|
|
//[ESP214]<Text>pwd=<user password>
|
|
case 214:
|
|
ESP214(cmd_params_pos, msg);
|
|
break;
|
|
#if defined(DISPLAY_TOUCH_DRIVER)
|
|
// Touch Calibration
|
|
//[ESP215]<CALIBRATE>[pwd=<user password>]
|
|
case 215:
|
|
ESP215(cmd_params_pos, msg);
|
|
break;
|
|
#endif // DISPLAY_TOUCH_DRIVER
|
|
#endif // DISPLAY_DEVICE
|
|
#ifdef BUZZER_DEVICE
|
|
// Play sound
|
|
//[ESP250]F=<frequency> D=<duration> [pwd=<user password>]
|
|
case 250:
|
|
ESP250(cmd_params_pos, msg);
|
|
break;
|
|
#endif // BUZZER_DEVICE
|
|
// Show pins
|
|
//[ESP220][pwd=<user password>]
|
|
case 220:
|
|
ESP220(cmd_params_pos, msg);
|
|
break;
|
|
// Delay command
|
|
//[ESP290]<delay in ms>[pwd=<user password>]
|
|
case 290:
|
|
ESP290(cmd_params_pos, msg);
|
|
break;
|
|
#if defined(ESP_LUA_INTERPRETER_FEATURE)
|
|
// Execute Lua script
|
|
//[ESP300]<filename>
|
|
case 300:
|
|
ESP300(cmd_params_pos, msg);
|
|
break;
|
|
// Query and Control ESP300 execution
|
|
//[ESP301]action=<PAUSE/RESUME/ABORT>
|
|
case 301:
|
|
ESP301(cmd_params_pos, msg);
|
|
break;
|
|
#endif // ESP_LUA_INTERPRETER_FEATURE
|
|
|
|
// Get full ESP3D settings
|
|
//[ESP400]<pwd=admin>
|
|
case 400:
|
|
ESP400(cmd_params_pos, msg);
|
|
break;
|
|
// Set EEPROM setting
|
|
//[ESP401]P=<position> T=<type> V=<value> pwd=<user/admin password>
|
|
case 401:
|
|
ESP401(cmd_params_pos, msg);
|
|
break;
|
|
#if defined(WIFI_FEATURE)
|
|
// Get available AP list (limited to 30)
|
|
// msg is JSON or plain text according parameter
|
|
//[ESP410]<plain>
|
|
case 410:
|
|
ESP410(cmd_params_pos, msg);
|
|
break;
|
|
#endif // WIFI_FEATURE
|
|
// Get ESP current status
|
|
// msg is JSON or plain text according parameter
|
|
//[ESP420]<plain>
|
|
case 420:
|
|
ESP420(cmd_params_pos, msg);
|
|
break;
|
|
// Set ESP State
|
|
// cmd are RESTART / RESET
|
|
//[ESP444]<cmd><pwd=admin>
|
|
case 444:
|
|
ESP444(cmd_params_pos, msg);
|
|
break;
|
|
#ifdef MDNS_FEATURE
|
|
// Get ESP3D list
|
|
//[ESP450] pwd=<admin/user password>
|
|
case 450:
|
|
ESP450(cmd_params_pos, msg);
|
|
break;
|
|
#endif // MDNS_FEATURE
|
|
#ifdef AUTHENTICATION_FEATURE
|
|
// Get current authentication level
|
|
//[ESP500] json=<no> pwd=<admin password>
|
|
case 500:
|
|
ESP500(cmd_params_pos, msg);
|
|
break;
|
|
// set/display session time out
|
|
//[ESP510]<password> json=<no> pwd=<admin password>
|
|
case 510:
|
|
ESP510(cmd_params_pos, msg);
|
|
break;
|
|
// Change admin password
|
|
//[ESP550]<password>pwd=<admin password>
|
|
case 550:
|
|
ESP550(cmd_params_pos, msg);
|
|
break;
|
|
// Change user password
|
|
//[ESP555]<password>pwd=<admin/user password>
|
|
case 555:
|
|
ESP555(cmd_params_pos, msg);
|
|
break;
|
|
#endif // AUTHENTICATION_FEATURE
|
|
#if defined(NOTIFICATION_FEATURE)
|
|
// Send Notification
|
|
//[ESP600]<msg>[pwd=<admin password>]
|
|
case 600:
|
|
ESP600(cmd_params_pos, msg);
|
|
break;
|
|
// Set/Get Notification settings
|
|
//[ESP610]type=<NONE/PUSHOVER/EMAIL/LINE/HOMEASSISTANT> T1=<token1>
|
|
// T2=<token2>
|
|
// TS=<Settings> pwd=<admin password> Get will give type and settings only
|
|
// not the protected T1/T2
|
|
case 610:
|
|
ESP610(cmd_params_pos, msg);
|
|
break;
|
|
// Send Notification using URL
|
|
//[ESP620]URL=<encoded url> pwd=<admin password>
|
|
case 620:
|
|
ESP620(cmd_params_pos, msg);
|
|
break;
|
|
#endif // NOTIFICATION_FEATURE
|
|
#if defined(FILESYSTEM_FEATURE)
|
|
// Format ESP Filesystem
|
|
//[ESP710]FORMAT pwd=<admin password>
|
|
case 710:
|
|
ESP710(cmd_params_pos, msg);
|
|
break;
|
|
// List ESP Filesystem
|
|
//[ESP720]<Root> pwd=<admin password>
|
|
case 720:
|
|
ESP720(cmd_params_pos, msg);
|
|
break;
|
|
// Action on ESP Filesystem
|
|
// rmdir / remove / mkdir / exists
|
|
//[ESP730]<Action>=<path> pwd=<admin password>
|
|
case 730:
|
|
ESP730(cmd_params_pos, msg);
|
|
break;
|
|
#endif // FILESYSTEM_FEATURE
|
|
#if defined(SD_DEVICE)
|
|
// Format ESP Filesystem
|
|
//[ESP715]FORMATSD pwd=<admin password>
|
|
case 715:
|
|
ESP715(cmd_params_pos, msg);
|
|
break;
|
|
#endif // SD_DEVICE
|
|
#if defined(GCODE_HOST_FEATURE)
|
|
// Open local file
|
|
//[ESP700]<filename>
|
|
case 700:
|
|
ESP700(cmd_params_pos, msg);
|
|
break;
|
|
// Get Status and Control ESP700 stream
|
|
//[ESP701]action=<PAUSE/RESUME/ABORT>
|
|
case 701:
|
|
ESP701(cmd_params_pos, msg);
|
|
break;
|
|
#endif // GCODE_HOST_FEATURE
|
|
#if defined(SD_DEVICE)
|
|
// List SD Filesystem
|
|
//[ESP740]<Root> pwd=<admin password>
|
|
case 740:
|
|
ESP740(cmd_params_pos, msg);
|
|
break;
|
|
// Action on SD Filesystem
|
|
// rmdir / remove / mkdir / exists
|
|
//[ESP750]<Action>=<path> pwd=<admin password>
|
|
case 750:
|
|
ESP750(cmd_params_pos, msg);
|
|
break;
|
|
#endif // SD_DEVICE
|
|
#if defined(GLOBAL_FILESYSTEM_FEATURE)
|
|
// List Global Filesystem
|
|
//[ESP780]<Root> pwd=<admin password>
|
|
case 780:
|
|
ESP780(cmd_params_pos, msg);
|
|
break;
|
|
// Action on Global Filesystem
|
|
// rmdir / remove / mkdir / exists
|
|
//[ESP790]<Action>=<path> pwd=<admin password>
|
|
case 790:
|
|
ESP790(cmd_params_pos, msg);
|
|
break;
|
|
#endif // GLOBAL_FILESYSTEM_FEATURE
|
|
// Get fw version firmare target and fw version
|
|
// eventually set time with pc time
|
|
// output is JSON or plain text according parameter
|
|
//[ESP800]<plain><time=YYYY-MM-DD-HH-MM-SS>
|
|
case 800:
|
|
ESP800(cmd_params_pos, msg);
|
|
break;
|
|
|
|
#if COMMUNICATION_PROTOCOL != SOCKET_SERIAL
|
|
// Get state / Set Enable / Disable Serial Communication
|
|
//[ESP900]<ENABLE/DISABLE>
|
|
case 900:
|
|
ESP900(cmd_params_pos, msg);
|
|
break;
|
|
// Get / Set Serial Baud Rate
|
|
//[ESP901]<BAUD RATE> json=<no> pwd=<admin/user password>
|
|
case 901:
|
|
ESP901(cmd_params_pos, msg);
|
|
break;
|
|
#endif // COMMUNICATION_PROTOCOL != SOCKET_SERIAL
|
|
#ifdef BUZZER_DEVICE
|
|
// Get state / Set Enable / Disable buzzer
|
|
//[ESP910]<ENABLE/DISABLE>
|
|
case 910:
|
|
ESP910(cmd_params_pos, msg);
|
|
break;
|
|
#endif // BUZZER_DEVICE
|
|
|
|
#if defined(ESP_SERIAL_BRIDGE_OUTPUT)
|
|
// Get state / Set Enable / Disable Serial Bridge Communication
|
|
//[ESP930]<ENABLE/DISABLE>
|
|
case 930:
|
|
ESP930(cmd_params_pos, msg);
|
|
break;
|
|
// Get / Set Serial Bridge Baud Rate
|
|
//[ESP931]<BAUD RATE> json=<no> pwd=<admin/user password>
|
|
case 931:
|
|
ESP931(cmd_params_pos, msg);
|
|
break;
|
|
#endif // defined(ESP_SERIAL_BRIDGE_OUTPUT)
|
|
#if defined(ARDUINO_ARCH_ESP32) && \
|
|
(CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32S2 || \
|
|
CONFIG_IDF_TARGET_ESP32C3)
|
|
case 999:
|
|
// Set quiet boot if strapping pin is High
|
|
//[ESP999]<QUIETBOOT> [pwd=<admin/user password>]
|
|
ESP999(cmd_params_pos, msg);
|
|
break;
|
|
#endif // ARDUINO_ARCH_ESP32
|
|
|
|
default:
|
|
msg->target = msg->origin;
|
|
esp3d_log("Invalid Command: %d", cmd);
|
|
if (hasTag(msg, cmd_params_pos, "json")) {
|
|
String tmpstr = "{\"cmd\":\"[ESP";
|
|
tmpstr += String(cmd);
|
|
tmpstr += "]\",\"status\":\"error\",\"data\":\"Invalid Command\"}";
|
|
if (!dispatch(msg, tmpstr.c_str())) {
|
|
esp3d_log_e("Out of memory");
|
|
}
|
|
} else {
|
|
String tmpstr = "Invalid Command: [ESP";
|
|
tmpstr += String(cmd);
|
|
tmpstr += "]\n";
|
|
if (!dispatch(msg, tmpstr.c_str())) {
|
|
esp3d_log_e("Out of memory");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool ESP3DCommands::dispatchSetting(bool json, const char *filter,
|
|
ESP3DSettingIndex index, const char *help,
|
|
const char **optionValues,
|
|
const char **optionLabels, uint32_t maxsize,
|
|
uint32_t minsize, uint32_t minsize2,
|
|
uint8_t precision, const char *unit,
|
|
bool needRestart, ESP3DClientType target,
|
|
ESP3DRequest requestId, bool isFirst) {
|
|
String tmpstr;
|
|
String value;
|
|
tmpstr.reserve(
|
|
350); // to save time and avoid several memories allocation delay
|
|
const ESP3DSettingDescription *elementSetting =
|
|
ESP3DSettings::getSettingPtr(index);
|
|
if (!elementSetting) {
|
|
return false;
|
|
}
|
|
switch (elementSetting->type) {
|
|
case ESP3DSettingType::byte_t:
|
|
value = String(ESP3DSettings::readByte(index));
|
|
break;
|
|
case ESP3DSettingType::integer_t:
|
|
value = String(ESP3DSettings::readUint32(index));
|
|
break;
|
|
case ESP3DSettingType::ip_t:
|
|
value = ESP3DSettings::readIPString(index);
|
|
break;
|
|
case ESP3DSettingType::float_t:
|
|
// TODO Add float support ?
|
|
value = "Not supported";
|
|
break;
|
|
case ESP3DSettingType::mask:
|
|
// TODO Add Mask support ?
|
|
value = "Not supported";
|
|
break;
|
|
case ESP3DSettingType::bitsfield:
|
|
// TODO Add bitfield support ?
|
|
value = "Not supported";
|
|
break;
|
|
default: // String
|
|
if (index == ESP_STA_PASSWORD || index == ESP_AP_PASSWORD ||
|
|
#if defined(ESP3D_NOTIFICATIONS_FEATURE)
|
|
index == ESP_NOTIFICATION_TOKEN1 ||
|
|
index == ESP_NOTIFICATION_TOKEN2 ||
|
|
#endif // ESP3D_NOTIFICATIONS_FEATURE
|
|
|
|
index == ESP_ADMIN_PWD || index == ESP_USER_PWD) { // hide passwords
|
|
// using ********
|
|
value = HIDDEN_PASSWORD;
|
|
} else {
|
|
value = ESP3DSettings::readString(index);
|
|
}
|
|
}
|
|
if (json) {
|
|
if (!isFirst) {
|
|
tmpstr += ",";
|
|
}
|
|
tmpstr += "{\"F\":\"";
|
|
tmpstr += filter;
|
|
tmpstr += "\",\"P\":\"";
|
|
tmpstr += String(static_cast<uint16_t>(index));
|
|
tmpstr += "\",\"T\":\"";
|
|
switch (elementSetting->type) {
|
|
case ESP3DSettingType::byte_t:
|
|
tmpstr += "B";
|
|
break;
|
|
case ESP3DSettingType::integer_t:
|
|
tmpstr += "I";
|
|
break;
|
|
case ESP3DSettingType::ip_t:
|
|
tmpstr += "A";
|
|
break;
|
|
case ESP3DSettingType::float_t:
|
|
tmpstr += "F";
|
|
break;
|
|
case ESP3DSettingType::mask:
|
|
tmpstr += "M";
|
|
break;
|
|
case ESP3DSettingType::bitsfield:
|
|
tmpstr += "X";
|
|
break;
|
|
default:
|
|
tmpstr += "S";
|
|
}
|
|
tmpstr += "\",\"V\":\"";
|
|
tmpstr += value; // TODO: need to encode string ?
|
|
tmpstr += "\",\"H\":\"";
|
|
tmpstr += help;
|
|
tmpstr += "\"";
|
|
if (needRestart) {
|
|
tmpstr += ",\"R\":\"1\"";
|
|
}
|
|
if (optionValues && optionLabels) {
|
|
tmpstr += ",\"O\":[";
|
|
for (uint8_t i = 0; i < maxsize; i++) {
|
|
if (i > 0) {
|
|
tmpstr += ",";
|
|
}
|
|
tmpstr += "{\"";
|
|
// be sure we have same size for both array to avoid overflow
|
|
tmpstr += optionLabels[i];
|
|
tmpstr += "\":\"";
|
|
tmpstr += optionValues[i];
|
|
tmpstr += "\"}";
|
|
}
|
|
tmpstr += "]";
|
|
}
|
|
if (unit) {
|
|
tmpstr += ",\"R\":\"";
|
|
tmpstr += unit;
|
|
tmpstr += "\"";
|
|
}
|
|
if (precision != ((uint8_t)-1)) {
|
|
tmpstr += ",\"E\":\"";
|
|
tmpstr += String(precision);
|
|
tmpstr += "\"";
|
|
}
|
|
if (maxsize != (uint32_t)-1 && !optionValues) {
|
|
tmpstr += ",\"S\":\"";
|
|
tmpstr += String(maxsize);
|
|
tmpstr += "\"";
|
|
}
|
|
if (minsize != (uint32_t)-1) {
|
|
tmpstr += ",\"M\":\"";
|
|
tmpstr += String(minsize);
|
|
tmpstr += "\"";
|
|
}
|
|
if (minsize2 != (uint32_t)-1) {
|
|
tmpstr += ",\"MS\":\"";
|
|
tmpstr += String(minsize2);
|
|
tmpstr += "\"";
|
|
}
|
|
tmpstr += "}";
|
|
} else {
|
|
tmpstr = filter;
|
|
tmpstr += "/";
|
|
tmpstr += help;
|
|
tmpstr += ": ";
|
|
tmpstr += value;
|
|
tmpstr += "\n";
|
|
}
|
|
return dispatch(tmpstr.c_str(), target, requestId, ESP3DMessageType::core);
|
|
}
|
|
|
|
bool ESP3DCommands::dispatchAuthenticationError(ESP3DMessage *msg, uint cmdid,
|
|
bool json) {
|
|
String tmpstr;
|
|
if (!msg) {
|
|
return false;
|
|
}
|
|
#if defined(HTTP_FEATURE) && defined(AUTHENTICATION_FEATURE)
|
|
if (msg->target == ESP3DClientType::http) {
|
|
msg->authentication_level = ESP3DAuthenticationLevel::not_authenticated;
|
|
}
|
|
#endif // HTTP_FEATURE
|
|
// answer is one message, override for safety
|
|
msg->type = ESP3DMessageType::unique;
|
|
if (json) {
|
|
tmpstr = "{\"cmd\":\"";
|
|
tmpstr += String(cmdid);
|
|
tmpstr +=
|
|
"\",\"status\":\"error\",\"data\":\"Wrong authentication level\"}";
|
|
} else {
|
|
tmpstr = "Wrong authentication level\n";
|
|
}
|
|
return dispatch(msg, tmpstr.c_str());
|
|
}
|
|
|
|
bool ESP3DCommands::dispatchAnswer(ESP3DMessage *msg, uint cmdid, bool json,
|
|
bool hasError, const char *answerMsg) {
|
|
String tmpstr;
|
|
if (!msg || !answerMsg) {
|
|
esp3d_log_e("no msg");
|
|
return false;
|
|
}
|
|
// answer is one message, override for safety
|
|
msg->type = ESP3DMessageType::unique;
|
|
if (json) {
|
|
tmpstr = "{\"cmd\":\"" + String(cmdid) + "\",\"status\":\"";
|
|
|
|
if (hasError) {
|
|
tmpstr += "error";
|
|
} else {
|
|
tmpstr += "ok";
|
|
}
|
|
tmpstr += "\",\"data\":";
|
|
if (answerMsg[0] != '{') {
|
|
tmpstr += "\"";
|
|
}
|
|
tmpstr += answerMsg;
|
|
if (answerMsg[0] != '{') {
|
|
tmpstr += "\"";
|
|
}
|
|
tmpstr += "}\n";
|
|
} else {
|
|
tmpstr = answerMsg;
|
|
tmpstr += "\n";
|
|
}
|
|
return dispatch(msg, tmpstr.c_str());
|
|
}
|
|
|
|
bool ESP3DCommands::dispatchKeyValue(bool json, const char *key,
|
|
const char *value, ESP3DClientType target,
|
|
ESP3DRequest requestId, bool nested,
|
|
bool isFirst) {
|
|
String tmpstr = "";
|
|
if (json) {
|
|
if (!isFirst) {
|
|
tmpstr += ",";
|
|
}
|
|
if (nested) {
|
|
tmpstr += "{";
|
|
}
|
|
tmpstr += "\"";
|
|
}
|
|
tmpstr += key;
|
|
if (json) {
|
|
tmpstr += "\":\"";
|
|
} else {
|
|
tmpstr += ": ";
|
|
}
|
|
tmpstr += value;
|
|
if (json) {
|
|
tmpstr += "\"";
|
|
if (nested) {
|
|
tmpstr += "}";
|
|
}
|
|
} else {
|
|
tmpstr += "\n";
|
|
}
|
|
return dispatch(tmpstr.c_str(), target, requestId, ESP3DMessageType::core);
|
|
}
|
|
|
|
bool ESP3DCommands::dispatchIdValue(bool json, const char *Id,
|
|
const char *value, ESP3DClientType target,
|
|
ESP3DRequest requestId, bool isFirst) {
|
|
String tmpstr = "";
|
|
if (json) {
|
|
if (!isFirst) {
|
|
tmpstr += ",";
|
|
}
|
|
tmpstr += "{\"id\":\"";
|
|
}
|
|
tmpstr += Id;
|
|
if (json) {
|
|
tmpstr += "\",\"value\":\"";
|
|
} else {
|
|
tmpstr += ": ";
|
|
}
|
|
tmpstr += value;
|
|
if (json) {
|
|
tmpstr += "\"}";
|
|
} else {
|
|
tmpstr += "\n";
|
|
}
|
|
return dispatch(tmpstr.c_str(), target, requestId, ESP3DMessageType::core);
|
|
}
|
|
|
|
bool ESP3DCommands::formatCommand(char *cmd, size_t len) {
|
|
if (isRealTimeCommand(cmd, len)) {
|
|
// TODO: what if is realtime command ?
|
|
return true;
|
|
}
|
|
uint sizestr = strlen(cmd);
|
|
if (len > sizestr + 2) {
|
|
cmd[sizestr] = '\n';
|
|
cmd[sizestr + 1] = 0x0;
|
|
return true;
|
|
}
|
|
if (sizestr == len && cmd[sizestr - 1] == '\n') {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ESP3DCommands::process(ESP3DMessage *msg) {
|
|
static bool lastIsESP3D = false;
|
|
if (!msg) {
|
|
esp3d_log_e("no msg");
|
|
return;
|
|
}
|
|
esp3d_log("Processing message %d", msg->size);
|
|
if (is_esp_command(msg->data, msg->size)) {
|
|
esp3d_log("Detected ESP command");
|
|
lastIsESP3D = true;
|
|
uint cmdId = 0;
|
|
uint espcmdpos = 0;
|
|
bool startcmd = false;
|
|
bool endcmd = false;
|
|
for (uint i = 0; i < msg->size && espcmdpos == 0; i++) {
|
|
if (char(msg->data[i]) == ']') { // start command flag
|
|
endcmd = true;
|
|
espcmdpos = i + 1;
|
|
} else if (char(msg->data[i]) == '[') { // end command flag
|
|
startcmd = true;
|
|
} else if (startcmd && !endcmd &&
|
|
std::isdigit(static_cast<unsigned char>(
|
|
char(msg->data[i])))) { // command id
|
|
if (cmdId != 0) {
|
|
cmdId = (cmdId * 10);
|
|
}
|
|
cmdId += (msg->data[i] - 48);
|
|
}
|
|
}
|
|
// execute esp command
|
|
esp3d_log("Execute internal command %d", cmdId);
|
|
execute_internal_command(cmdId, espcmdpos, msg);
|
|
} 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
|
|
// part of previous ESP3D command
|
|
if (msg->size == 1 &&
|
|
((char(msg->data[0]) == '\n') || (char(msg->data[0]) == '\r')) &&
|
|
lastIsESP3D) {
|
|
lastIsESP3D = false;
|
|
// delete message
|
|
esp3d_log("Delete message");
|
|
esp3d_message_manager.deleteMsg(msg);
|
|
return;
|
|
}
|
|
lastIsESP3D = false;
|
|
esp3d_log("Dispatch message: %s", msg->data);
|
|
dispatch(msg);
|
|
}
|
|
}
|
|
bool ESP3DCommands::dispatch(ESP3DMessage *msg, const char *sbuf) {
|
|
return dispatch(msg, (uint8_t *)sbuf, strlen(sbuf));
|
|
}
|
|
|
|
bool ESP3DCommands::dispatch(ESP3DMessage *msg, uint8_t *sbuf, size_t len) {
|
|
if (!msg) {
|
|
esp3d_log_e("no msg");
|
|
return false;
|
|
}
|
|
// check is need \n at the end of the command
|
|
if (msg->type == ESP3DMessageType::unique ||
|
|
msg->type == ESP3DMessageType::tail) {
|
|
esp3d_log("unique or tail message :*%s*", (char *)sbuf);
|
|
if (!formatCommand((char *)sbuf, len)) {
|
|
esp3d_log("format command failed");
|
|
String tmpstr = "";
|
|
tmpstr.reserve(len + 2);
|
|
for (uint i = 0; i < len; i++) {
|
|
tmpstr += char(sbuf[i]);
|
|
}
|
|
tmpstr += '\n';
|
|
esp3d_log("update command success: *%s*", tmpstr.c_str());
|
|
if (!esp3d_message_manager.setDataContent(msg, (uint8_t *)tmpstr.c_str(),
|
|
tmpstr.length())) {
|
|
esp3d_log_e("set data content failed");
|
|
esp3d_message_manager.deleteMsg(msg);
|
|
return false;
|
|
}
|
|
} else {
|
|
esp3d_log("format command success, no need to update");
|
|
if (!esp3d_message_manager.setDataContent(msg, sbuf, len)) {
|
|
esp3d_log_e("set data content failed");
|
|
esp3d_message_manager.deleteMsg(msg);
|
|
return false;
|
|
}
|
|
}
|
|
} else {
|
|
esp3d_log("not unique or tail message");
|
|
if (!esp3d_message_manager.setDataContent(msg, sbuf, len)) {
|
|
esp3d_log_e("set data content failed");
|
|
esp3d_message_manager.deleteMsg(msg);
|
|
return false;
|
|
}
|
|
}
|
|
return dispatch(msg);
|
|
}
|
|
|
|
bool ESP3DCommands::dispatch(uint8_t *sbuf, size_t size, ESP3DClientType target,
|
|
ESP3DRequest requestId, ESP3DMessageType type,
|
|
ESP3DClientType origin,
|
|
ESP3DAuthenticationLevel authentication_level) {
|
|
ESP3DMessage *newMsgPtr = esp3d_message_manager.newMsg(origin, target);
|
|
if (newMsgPtr) {
|
|
newMsgPtr->request_id = requestId;
|
|
newMsgPtr->type = type;
|
|
newMsgPtr->authentication_level = authentication_level;
|
|
return dispatch(newMsgPtr, sbuf, size);
|
|
}
|
|
esp3d_log_e("no newMsgPtr");
|
|
return false;
|
|
}
|
|
bool ESP3DCommands::dispatch(const char *sbuf, ESP3DClientType target,
|
|
ESP3DRequest requestId, ESP3DMessageType type,
|
|
ESP3DClientType origin,
|
|
ESP3DAuthenticationLevel authentication_level) {
|
|
ESP3DMessage *newMsgPtr = esp3d_message_manager.newMsg(origin, target);
|
|
if (newMsgPtr) {
|
|
newMsgPtr->request_id = requestId;
|
|
newMsgPtr->type = type;
|
|
newMsgPtr->authentication_level = authentication_level;
|
|
return dispatch(newMsgPtr, sbuf);
|
|
}
|
|
esp3d_log_e("no newMsgPtr");
|
|
return false;
|
|
}
|
|
|
|
ESP3DClientType ESP3DCommands::getOutputClient(bool fromSettings) {
|
|
// TODO: add setting for it when necessary
|
|
(void)fromSettings;
|
|
esp3d_log("OutputClient: %d %s", static_cast<uint8_t>(_output_client),
|
|
GETCLIENTSTR(_output_client));
|
|
return _output_client;
|
|
}
|
|
|
|
bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
|
|
bool sendOk = true;
|
|
String tmp;
|
|
esp3d_log("Dispatch message data: %s", (const char *)msg->data);
|
|
if (!msg) {
|
|
esp3d_log_e("no msg");
|
|
return false;
|
|
}
|
|
// currently only echo back no test done on success
|
|
// TODO check add is successful
|
|
switch (msg->target) {
|
|
case ESP3DClientType::no_client:
|
|
esp3d_log("No client message");
|
|
esp3d_message_manager.deleteMsg(msg);
|
|
break;
|
|
#if COMMUNICATION_PROTOCOL == RAW_SERIAL
|
|
case ESP3DClientType::serial:
|
|
esp3d_log("Serial message");
|
|
if (!esp3d_serial_service.dispatch(msg)) {
|
|
sendOk = false;
|
|
esp3d_log_e("Serial dispatch failed");
|
|
}
|
|
break;
|
|
#endif // COMMUNICATION_PROTOCOL == RAW_SERIAL
|
|
|
|
#if COMMUNICATION_PROTOCOL == SOCKET_SERIAL
|
|
case ESP3DClientType::echo_serial:
|
|
esp3d_log("Echo serial message");
|
|
MYSERIAL1.write(msg->data, msg->size);
|
|
if (msg->type == ESP3DMessageType::unique ||
|
|
msg->type == ESP3DMessageType::tail) {
|
|
if (msg->data[msg->size - 1] != '\n') {
|
|
MYSERIAL1.write('\n');
|
|
}
|
|
}
|
|
esp3d_message_manager.deleteMsg(msg);
|
|
break;
|
|
|
|
case ESP3DClientType::socket_serial:
|
|
esp3d_log("Socket serial message");
|
|
if (!Serial2Socket.dispatch(msg)) {
|
|
sendOk = false;
|
|
esp3d_log_e("Socket dispatch failed");
|
|
}
|
|
break;
|
|
#endif // COMMUNICATION_PROTOCOL == SOCKET_SERIAL
|
|
|
|
#if defined(ESP_LUA_INTERPRETER_FEATURE)
|
|
case ESP3DClientType::lua_script:
|
|
esp3d_log("Lua script message");
|
|
if (!esp3d_lua_interpreter.dispatch(msg)) {
|
|
sendOk = false;
|
|
esp3d_log_e("Lua script dispatch failed");
|
|
}
|
|
break;
|
|
#endif // ESP_LUA_INTERPRETER_FEATURE
|
|
|
|
#if defined(ESP_SERIAL_BRIDGE_OUTPUT)
|
|
case ESP3DClientType::serial_bridge:
|
|
esp3d_log("Serial bridge message");
|
|
if (!serial_bridge_service.dispatch(msg)) {
|
|
sendOk = false;
|
|
esp3d_log_e("Serial bridge dispatch failed");
|
|
}
|
|
break;
|
|
#endif // ESP_SERIAL_BRIDGE_OUTPUT
|
|
|
|
#ifdef WS_DATA_FEATURE
|
|
case ESP3DClientType::websocket:
|
|
esp3d_log("Websocket message");
|
|
if (!websocket_data_server.dispatch(msg)) {
|
|
sendOk = false;
|
|
esp3d_log_e("Telnet dispatch failed");
|
|
}
|
|
break;
|
|
#endif // WS_DATA_FEATURE
|
|
|
|
#ifdef TELNET_FEATURE
|
|
case ESP3DClientType::telnet:
|
|
esp3d_log("Telnet message");
|
|
if (!telnet_server.dispatch(msg)) {
|
|
sendOk = false;
|
|
esp3d_log_e("Telnet dispatch failed");
|
|
}
|
|
break;
|
|
#endif // TELNET_FEATURE
|
|
|
|
#ifdef BLUETOOTH_FEATURE
|
|
case ESP3DClientType::bluetooth:
|
|
esp3d_log("Bluetooth message");
|
|
if (!bt_service.dispatch(msg)) {
|
|
sendOk = false;
|
|
esp3d_log_e("Bluetooth dispatch failed");
|
|
}
|
|
break;
|
|
#endif // BLUETOOTH_FEATURE
|
|
|
|
#ifdef HTTP_FEATURE
|
|
case ESP3DClientType::webui_websocket:
|
|
esp3d_log("Webui websocket message");
|
|
if (!websocket_terminal_server.dispatch(msg)) {
|
|
sendOk = false;
|
|
esp3d_log_e("Webui websocket dispatch failed");
|
|
}
|
|
break;
|
|
case ESP3DClientType::http:
|
|
esp3d_log("Http message");
|
|
if (!HTTP_Server::dispatch(msg)) {
|
|
sendOk = false;
|
|
esp3d_log_e("Webui websocket dispatch failed");
|
|
}
|
|
break;
|
|
#endif // HTTP_FEATURE
|
|
#if defined(DISPLAY_DEVICE)
|
|
case ESP3DClientType::rendering:
|
|
esp3d_log("Rendering message");
|
|
if (!esp3d_display.dispatch(msg)) {
|
|
sendOk = false;
|
|
esp3d_log_e("Display dispatch failed");
|
|
}
|
|
break;
|
|
#endif // defined(DISPLAY_DEVICE)
|
|
|
|
#if COMMUNICATION_PROTOCOL == MKS_SERIAL
|
|
case ESP3DClientType::mks_serial:
|
|
esp3d_log("MKS Serial message");
|
|
if (!MKSService::dispatch(msg)) {
|
|
sendOk = false;
|
|
esp3d_log_e("MKS Serial dispatch failed");
|
|
}
|
|
break;
|
|
#endif // COMMUNICATION_PROTOCOL == MKS_SERIAL
|
|
|
|
#ifdef PRINTER_HAS_DISPLAY
|
|
case ESP3DClientType::remote_screen:
|
|
esp3d_log("Remote screen message");
|
|
// change target to output client
|
|
msg->target = getOutputClient();
|
|
// change text to GCODE M117
|
|
tmp = "M117 ";
|
|
tmp += (const char *)msg->data;
|
|
// replace end of line with space
|
|
tmp.replace("\n", " ");
|
|
tmp.replace("\r", "");
|
|
tmp += "\n";
|
|
if (esp3d_message_manager.setDataContent(msg, (uint8_t *)tmp.c_str(),
|
|
tmp.length())) {
|
|
return dispatch(msg);
|
|
}
|
|
sendOk = false;
|
|
esp3d_log_e("Cannot set data content for remote screen");
|
|
break;
|
|
#endif // PRINTER_HAS_DISPLAY
|
|
case ESP3DClientType::all_clients:
|
|
esp3d_log("All clients message");
|
|
// Add each client one by one
|
|
#ifdef PRINTER_HAS_DISPLAY
|
|
if (msg->origin != ESP3DClientType::remote_screen &&
|
|
msg->origin != getOutputClient()) {
|
|
if (msg->target == ESP3DClientType::all_clients) {
|
|
// become the reference message
|
|
msg->target = ESP3DClientType::remote_screen;
|
|
} else {
|
|
// duplicate message because current is already pending
|
|
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
|
|
if (copy_msg) {
|
|
copy_msg->target = ESP3DClientType::remote_screen;
|
|
dispatch(copy_msg);
|
|
} else {
|
|
esp3d_log_e("Cannot duplicate message for remote screen");
|
|
}
|
|
}
|
|
}
|
|
#endif // PRINTER_HAS_DISPLAY
|
|
|
|
#if defined(ESP_LUA_INTERPRETER_FEATURE)
|
|
if (msg->origin != ESP3DClientType::lua_script &&
|
|
msg->origin == getOutputClient() && esp3d_lua_interpreter.isScriptRunning()) {
|
|
if (msg->target == ESP3DClientType::all_clients) {
|
|
// become the reference message
|
|
msg->target = ESP3DClientType::lua_script;
|
|
} else {
|
|
// duplicate message because current is already pending
|
|
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
|
|
if (copy_msg) {
|
|
copy_msg->target = ESP3DClientType::lua_script;
|
|
dispatch(copy_msg);
|
|
} else {
|
|
esp3d_log_e("Cannot duplicate message for lua script");
|
|
}
|
|
}
|
|
}
|
|
#endif // ESP_LUA_INTERPRETER_FEATURE
|
|
|
|
#if defined(DISPLAY_DEVICE)
|
|
if (msg->origin != ESP3DClientType::rendering &&
|
|
msg->origin != getOutputClient()) {
|
|
if (msg->target == ESP3DClientType::all_clients) {
|
|
// become the reference message
|
|
msg->target = ESP3DClientType::rendering;
|
|
msg->request_id.id = ESP_OUTPUT_STATUS;
|
|
} else {
|
|
// duplicate message because current is already pending
|
|
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
|
|
if (copy_msg) {
|
|
copy_msg->target = ESP3DClientType::rendering;
|
|
copy_msg->request_id.id = ESP_OUTPUT_STATUS;
|
|
dispatch(copy_msg);
|
|
} else {
|
|
esp3d_log_e("Cannot duplicate message for display");
|
|
}
|
|
}
|
|
}
|
|
#endif // defined(DISPLAY_DEVICE)
|
|
|
|
#if COMMUNICATION_PROTOCOL == SOCKET_SERIAL
|
|
if (msg->origin != ESP3DClientType::echo_serial &&
|
|
msg->origin != ESP3DClientType::socket_serial) {
|
|
if (msg->target == ESP3DClientType::all_clients) {
|
|
// become the reference message
|
|
msg->target = ESP3DClientType::echo_serial;
|
|
} else {
|
|
// duplicate message because current is already pending
|
|
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
|
|
if (copy_msg) {
|
|
copy_msg->target = ESP3DClientType::echo_serial;
|
|
dispatch(copy_msg);
|
|
} else {
|
|
esp3d_log_e("Cannot duplicate message for echo serial");
|
|
}
|
|
}
|
|
}
|
|
#endif // COMMUNICATION_PROTOCOL == SOCKET_SERIAL
|
|
|
|
#if defined(ESP_SERIAL_BRIDGE_OUTPUT)
|
|
if (msg->origin != ESP3DClientType::serial_bridge) {
|
|
if (msg->target == ESP3DClientType::all_clients) {
|
|
// become the reference message
|
|
msg->target = ESP3DClientType::serial_bridge;
|
|
} else {
|
|
// duplicate message because current is already pending
|
|
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
|
|
if (copy_msg) {
|
|
copy_msg->target = ESP3DClientType::serial_bridge;
|
|
dispatch(copy_msg);
|
|
} else {
|
|
esp3d_log_e("Cannot duplicate message for serial bridge");
|
|
}
|
|
}
|
|
}
|
|
#endif // ESP_SERIAL_BRIDGE_OUTPUT
|
|
|
|
#ifdef BLUETOOTH_FEATURE
|
|
if (msg->origin != ESP3DClientType::bluetooth &&
|
|
bt_service.isConnected()) {
|
|
if (msg->target == ESP3DClientType::all_clients) {
|
|
// become the reference message
|
|
msg->target = ESP3DClientType::bluetooth;
|
|
} else {
|
|
// duplicate message because current is already pending
|
|
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
|
|
if (copy_msg) {
|
|
copy_msg->target = ESP3DClientType::bluetooth;
|
|
dispatch(copy_msg);
|
|
} else {
|
|
esp3d_log_e("Cannot duplicate message for bluetooth");
|
|
}
|
|
}
|
|
}
|
|
#endif // BLUETOOTH_FEATURE
|
|
|
|
#ifdef TELNET_FEATURE
|
|
if (msg->origin != ESP3DClientType::telnet &&
|
|
telnet_server.isConnected()) {
|
|
if (msg->target == ESP3DClientType::all_clients) {
|
|
// become the reference message
|
|
msg->target = ESP3DClientType::telnet;
|
|
} else {
|
|
// duplicate message because current is already pending
|
|
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
|
|
if (copy_msg) {
|
|
copy_msg->target = ESP3DClientType::telnet;
|
|
dispatch(copy_msg);
|
|
} else {
|
|
esp3d_log_e("Cannot duplicate message for telnet");
|
|
}
|
|
}
|
|
} else {
|
|
if (msg->origin != ESP3DClientType::telnet)
|
|
esp3d_log("Telnet not connected");
|
|
}
|
|
#endif // TELNET_FEATURE
|
|
|
|
#ifdef HTTP_FEATURE // http cannot be in all client because it depend of any
|
|
// connection of the server
|
|
if (msg->origin != ESP3DClientType::webui_websocket &&
|
|
websocket_terminal_server.isConnected()) {
|
|
if (msg->target == ESP3DClientType::all_clients) {
|
|
// become the reference message
|
|
msg->target = ESP3DClientType::webui_websocket;
|
|
} else {
|
|
// duplicate message because current is already pending
|
|
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
|
|
if (copy_msg) {
|
|
copy_msg->target = ESP3DClientType::webui_websocket;
|
|
dispatch(copy_msg);
|
|
} else {
|
|
esp3d_log_e("Cannot duplicate message for webui_websocket");
|
|
}
|
|
}
|
|
} else {
|
|
if (msg->origin != ESP3DClientType::webui_websocket)
|
|
esp3d_log("Webui websocket not connected");
|
|
}
|
|
#endif // HTTP_FEATURE
|
|
|
|
#ifdef WS_DATA_FEATURE
|
|
if (msg->origin != ESP3DClientType::websocket &&
|
|
websocket_data_server.isConnected()) {
|
|
if (msg->target == ESP3DClientType::all_clients) {
|
|
// become the reference message
|
|
msg->target = ESP3DClientType::websocket;
|
|
} else {
|
|
// duplicate message because current is already pending
|
|
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
|
|
if (copy_msg) {
|
|
copy_msg->target = ESP3DClientType::websocket;
|
|
dispatch(copy_msg);
|
|
} else {
|
|
esp3d_log_e("Cannot duplicate message for websocket");
|
|
}
|
|
}
|
|
} else {
|
|
if (msg->origin != ESP3DClientType::websocket)
|
|
esp3d_log("Websocket not connected");
|
|
}
|
|
#endif // WS_DATA_FEATURE
|
|
|
|
//...
|
|
|
|
// Send pending if any or cancel message is no client did handle it
|
|
if (msg->target == ESP3DClientType::all_clients) {
|
|
esp3d_log("No client handled message, send pending");
|
|
sendOk = false;
|
|
} else {
|
|
return dispatch(msg);
|
|
}
|
|
break;
|
|
default:
|
|
esp3d_log_e("No valid target specified %d for %s",
|
|
static_cast<uint8_t>(msg->target), (char *)msg->data);
|
|
sendOk = false;
|
|
}
|
|
// clear message
|
|
if (!sendOk) {
|
|
esp3d_log_e("Send msg failed");
|
|
esp3d_message_manager.deleteMsg(msg);
|
|
}
|
|
return sendOk;
|
|
}
|