add [ESP700]support for FS

Add Header for FS file name
Add flag for FILESYSTEM_FEATURE in sources
do some AStyle
Change line number from uint16_t to uint32_t
This commit is contained in:
Luc 2019-10-02 22:48:23 +08:00
parent f7dd60c39f
commit 027ab132ae
9 changed files with 286 additions and 120 deletions

View File

@ -154,7 +154,7 @@
//Allow remote access by enabling cross origin access
//check https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
//this should be enabled only in specific cases
//this should be enabled only in specific cases
//like show the camera in web page different than device web server
//if you do not know what is that then better left it commented
//#define ESP_ACCESS_CONTROL_ALLOW_ORIGIN

View File

@ -499,12 +499,19 @@ bool Commands::execute_internal_command (int cmd, const char* cmd_params, level_
response = ESP610(cmd_params, auth_type, output);
break;
#endif //NOTIFICATION_FEATURE
#ifdef FILESYSTEM_FEATURE
#if defined(FILESYSTEM_FEATURE)
//Format ESP Filesystem
//[ESP710]FORMAT pwd=<admin password>
case 710:
response = ESP710(cmd_params, auth_type, output);
break;
#endif //FILESYSTEM_FEATURE
#ifdef FILESYSTEM_FEATURE
//Open local file
//[ESP700]<filname>
case 700:
response = ESP700(cmd_params, auth_type, output);
break;
//List ESP Filesystem
//[ESP720]<Root> pwd=<admin password>

View File

@ -112,6 +112,9 @@ public:
bool ESP600(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
bool ESP610(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
#endif //NOTIFICATION_FEATURE
#if defined(FILESYSTEM_FEATURE)
bool ESP700(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
#endif //FILESYSTEM_FEATURE
#if defined(FILESYSTEM_FEATURE)
bool ESP710(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
bool ESP720(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);

View File

@ -0,0 +1,50 @@
/*
ESP700.cpp - ESP3D command class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
This library 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 library 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 library; 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 defined (FILESYSTEM_FEATURE)
#include "../commands.h"
#include "../esp3doutput.h"
#include "../settings_esp3d.h"
#include "../../modules/authentication/authentication_service.h"
#include "../../modules/filesystem/esp_filesystem.h"
#include "../../modules/gcode_host/gcode_host.h"
////read local file
//[ESP700]<filename>
bool Commands::ESP700(const char* cmd_params, level_authenticate_type auth_type, ESP3DOutput * output)
{
bool response = true;
String parameter;
parameter = get_param (cmd_params, "");
#ifdef AUTHENTICATION_FEATURE
if (auth_type != LEVEL_ADMIN) {
output->printERROR("Wrong authentication!", 401);
response = false;
} else
#else
(void)auth_type;
#endif //AUTHENTICATION_FEATURE
{
esp3d_gcode_host.processFile(parameter.c_str(), auth_type, output);
output->printMSG("ok");
}
return response;
}
#endif //FILESYSTEM_FEATURE

View File

@ -55,7 +55,7 @@ static esp_err_t stream_handler(httpd_req_t *req)
}
esp3d_camera.connect(true);
#ifdef ESP_ACCESS_CONTROL_ALLOW_ORIGIN
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
#endif //ESP_ACCESS_CONTROL_ALLOw_ORIGIN
camera_fb_t * fb = NULL;
esp_err_t res = ESP_OK;

View File

@ -18,6 +18,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../../include/esp3d_config.h"
#ifdef FILESYSTEM_FEATURE
#include "esp_filesystem.h"
#include "../../core/genLinkedList.h"
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
@ -215,3 +216,5 @@ ESP_File& ESP_File::operator=(const ESP_File & other)
#endif //FILESYSTEM_TIMESTAMP_FEATURE
return *this;
}
#endif //FILESYSTEM_FEATURE

View File

@ -28,6 +28,8 @@
#define ESP_FILE_WRITE 1
#define ESP_FILE_APPEND 2
#define ESP_FLASH_FS_HEADER "/FS:"
#define ESP_MAX_OPENHANDLE 4
class ESP_File

View File

@ -22,7 +22,9 @@
#ifdef ESP_GCODE_HOST_FEATURE
#include "gcode_host.h"
#include "../../core/settings_esp3d.h"
#include "../../core/commands.h"
#include "../serial/serial_service.h"
#include "../filesystem/esp_filesystem.h"
GcodeHost esp3d_gcode_host;
@ -54,104 +56,111 @@ void GcodeHost::handle()
{
}
uint8_t GcodeHost::Checksum(const char * command, uint16_t commandSize)
uint8_t GcodeHost::Checksum(const char * command, uint32_t commandSize)
{
uint8_t checksum_val =0;
if (command == NULL) return 0;
for (uint16_t i=0; i < commandSize; i++)
{
checksum_val = checksum_val ^ ((uint8_t)command[i]);
}
if (command == NULL) {
return 0;
}
for (uint32_t i=0; i < commandSize; i++) {
checksum_val = checksum_val ^ ((uint8_t)command[i]);
}
return checksum_val;
}
String GcodeHost::CheckSumCommand(const char* command, uint16_t commandnb){
String commandchecksum = "N" + String((uint16_t)commandnb)+ " " + command;
String GcodeHost::CheckSumCommand(const char* command, uint32_t commandnb)
{
String commandchecksum = "N" + String((uint32_t)commandnb)+ " " + command;
uint8_t crc = Checksum(commandchecksum.c_str(), commandchecksum.length());
commandchecksum+="*"+String(crc);
return commandchecksum;
}
size_t GcodeHost::wait_for_data(uint32_t timeout){
size_t GcodeHost::wait_for_data(uint32_t timeout)
{
uint32_t start = millis();
while ((serial_service.available() < 2) && ((millis()-start) < timeout))
{
Hal::wait (0); //minimum delay is 10 actually
}
while ((serial_service.available() < 2) && ((millis()-start) < timeout)) {
Hal::wait (0); //minimum delay is 10 actually
}
return serial_service.available();
}
bool GcodeHost::resetCommandNumbering(){
bool GcodeHost::resetCommandNumbering()
{
String resetcmd = "M110 N0";
if (Settings_ESP3D::GetFirmwareTarget() == SMOOTHIEWARE)resetcmd = "N0 M110";
else resetcmd = "M110 N0";
if (Settings_ESP3D::GetFirmwareTarget() == SMOOTHIEWARE) {
resetcmd = "N0 M110";
} else {
resetcmd = "M110 N0";
}
_commandnumber = 1;
return sendCommand(resetcmd.c_str());
}
/*bool GcodeHost::endUpload(){
return true;
}*/
bool GcodeHost::wait_for_ack(uint32_t timeout, bool checksum, const char * ack){
bool GcodeHost::wait_for_ack(uint32_t timeout, bool checksum, const char * ack)
{
_needcommandnumber = _commandnumber;
uint32_t start = millis();
String answer = "";
while ((millis()-start) < timeout)
{
size_t len = serial_service.available();
if (len > 0){
uint8_t * sbuf = (uint8_t *)malloc(len+1);
if(!sbuf){
_error = ERROR_MEMORY_PROBLEM;
return false;
while ((millis()-start) < timeout) {
size_t len = serial_service.available();
if (len > 0) {
uint8_t * sbuf = (uint8_t *)malloc(len+1);
if(!sbuf) {
_error = ERROR_MEMORY_PROBLEM;
return false;
}
sbuf[len] = '\0';
answer+= (const char *)sbuf;
free(sbuf);
log_esp3d("Answer: %s",answer.c_str());
//check for ack
if (ack!=nullptr) {
if (answer.indexOf(ack) != -1) {
_error = ERROR_NO_ERROR;
return true;
}
sbuf[len] = '\0';
answer+= (const char *)sbuf;
free(sbuf);
log_esp3d("Answer: %s",anwer.c_str());
//check for ack
if (ack!=nullptr){
if (answer.indexOf(ack) != -1){
_error = ERROR_NO_ERROR;
return true;
}
} else{
if (answer.indexOf("ok") != -1){
if (!checksum){
_error = ERROR_NO_ERROR;
return true;
} else{
//check number
String ackstring = "ok " + String(_commandnumber);
if (answer.indexOf(ackstring) != -1){
_error = ERROR_NO_ERROR;
return true;
}
} else {
//wait is not an ack as it can appear any time
if (answer.indexOf("ok") != -1) {
if (!checksum) {
_error = ERROR_NO_ERROR;
return true;
} else {
//check number
String ackstring = "ok " + String(_commandnumber);
if (answer.indexOf(ackstring) != -1) {
_error = ERROR_NO_ERROR;
return true;
}
}
}
//check for error
if ((answer.indexOf("Resend:") != -1) || (answer.indexOf("rs N") != -1)){
_needcommandnumber = Get_commandNumber(answer);
if (_needcommandnumber == _commandnumber) {
_error = ERROR_RESEND;
} else {
_error = ERROR_NUMBER_MISMATCH;
log_esp3d("Error provived %d but need %d", _commandnumber, _needcommandnumber);
}
return false;
}
if (answer.indexOf("skip") != -1){
_error = ERROR_LINE_IGNORED;
return false;
}
}
Hal::wait (0); //minimum delay is 10 actually
//check for error
if ((answer.indexOf("Resend:") != -1) || (answer.indexOf("rs N") != -1)) {
_needcommandnumber = Get_commandNumber(answer);
if (_needcommandnumber == _commandnumber) {
_error = ERROR_RESEND;
} else {
_error = ERROR_NUMBER_MISMATCH;
log_esp3d("Error provived %d but need %d", _commandnumber, _needcommandnumber);
}
return false;
}
if (answer.indexOf("skip") != -1) {
_error = ERROR_LINE_IGNORED;
return false;
}
}
Hal::wait (0); //minimum delay is 10 actually
}
_error = ERROR_ACK_NUMBER;
return false;
}
@ -161,18 +170,19 @@ bool GcodeHost::wait_for_ack(uint32_t timeout, bool checksum, const char * ack){
//others error cancel the sending
//number mismatch / skip / timeout error must be managed out of this function
//line number incrementation is not done in this function neither
bool GcodeHost::sendCommand(const char* command, bool checksum, bool wait4ack, const char * ack){
bool GcodeHost::sendCommand(const char* command, bool checksum, bool wait4ack, const char * ack)
{
log_esp3d("Send command: %s", command);
String s;
if(checksum){
if(checksum) {
s = CheckSumCommand(command, _commandnumber);
} else{
s = command;
} else {
s = command;
}
for(uint8_t try_nb = 0; try_nb < MAX_TRY_2_SEND; try_nb ++) {
_error = ERROR_NO_ERROR;
purge();
if ((_error != ERROR_NO_ERROR) && wait4ack){
if ((_error != ERROR_NO_ERROR) && wait4ack) {
return false;
} else {
//if no need to wait for ack the purge has no real impact but clear buffer
@ -182,53 +192,54 @@ bool GcodeHost::sendCommand(const char* command, bool checksum, bool wait4ack, c
//to give a chance to not overload buffer
bool done = false;
while (((millis() - start) < DEFAULT_TIMOUT) && !done) {
if (serial_service.availableForWrite() > s.length()){
if (serial_service.availableForWrite() > s.length()) {
if (strlen(command) == serial_service.write((const uint8_t*)s.c_str(), s.length())) {
if (serial_service.write('\n')==1){
if(!wait4ack){
if (serial_service.write('\n')==1) {
if(!wait4ack) {
log_esp3d("No need ack");
return true;
}
//process answer
if (wait_for_ack(DEFAULT_TIMOUT, ack)) {
//process answer
if (wait_for_ack(DEFAULT_TIMOUT, ack)) {
log_esp3d("Command got ack");
return true;
} else {
//what is the error ?
log_esp3d("Error: %d", _error);
//no need to retry for this one
if (_error == ERROR_MEMORY_PROBLEM) {
return false;
}
//need to resend command
if (_error == ERROR_RESEND) {
done = true;
}
//the printer ask for another command line so exit
if ((_error == ERROR_NUMBER_MISMATCH) || (_error == ERROR_LINE_IGNORED)){
return false;
}
}
return true;
} else {
//what is the error ?
log_esp3d("Error: %d", _error);
//no need to retry for this one
if (_error == ERROR_MEMORY_PROBLEM) {
return false;
}
//need to resend command
if (_error == ERROR_RESEND) {
done = true;
}
//the printer ask for another command line so exit
if ((_error == ERROR_NUMBER_MISMATCH) || (_error == ERROR_LINE_IGNORED)) {
return false;
}
}
}
}
}
}
}
if (_error == ERROR_NO_ERROR) {
_error = ERROR_CANNOT_SEND_DATA;
_error = ERROR_CANNOT_SEND_DATA;
log_esp3d("Error: %d", _error);
}
return false;
}
bool GcodeHost::purge(uint32_t timeout){
bool GcodeHost::purge(uint32_t timeout)
{
uint32_t start = millis();
uint8_t buf [51];
_error = 0;
log_esp3d("Purge started")
while (serial_service.available() > 0){
log_esp3d("Purge started");
while (serial_service.available() > 0) {
if ((millis() - start ) > timeout) {
log_esp3d("Purge timeout\r\n")
log_esp3d("Purge timeout\r\n");
_error = ERROR_TIME_OUT;
return false;
}
@ -238,33 +249,105 @@ bool GcodeHost::purge(uint32_t timeout){
if ( (Settings_ESP3D::GetFirmwareTarget() == REPETIER4DV) || (Settings_ESP3D::GetFirmwareTarget() == REPETIER) || _waitwhenidle) {
String s = (const char *)buf;
//repetier never stop sending data so no need to wait if have 'wait' or 'busy'
if((s.indexOf ("wait") > -1) || (s.indexOf ("busy") > -1))return true;
log_esp3d("Impossible to purge\r\n")
if((s.indexOf ("wait") > -1) || (s.indexOf ("busy") > -1)) {
return true;
}
log_esp3d("Impossible to purge\r\n");
}
Hal::wait (0);
}
log_esp3d("Purge done")
return true;
}
log_esp3d("Purge done");
return true;
}
uint16_t GcodeHost::Get_commandNumber(String & response){
int64_t l = 0;
uint32_t GcodeHost::Get_commandNumber(String & response)
{
uint32_t l = 0;
String sresend = "Resend:";
if ( Settings_ESP3D::GetFirmwareTarget() == SMOOTHIEWARE){
if ( Settings_ESP3D::GetFirmwareTarget() == SMOOTHIEWARE) {
sresend = "rs N";
}
int pos = response.indexOf(sresend);
if (pos == -1 ) {
log_esp3d("Cannot find label", _error);
return -1;
}
}
pos+=sresend.length();
int pos2 = response.indexOf("\n", pos);
String snum = response.substring(pos, pos2);
//remove potential unwished char
snum.replace("\r", "");
l = snum.toInt();
log_esp3d("Command number to resend is %s", String(l).c_str());
log_esp3d("Command number to resend is %s", String((uint32_t)l).c_str());
return l;
}
bool GcodeHost::processFSFile(const char * filename, level_authenticate_type auth_type, ESP3DOutput * output)
{
bool res = true;
log_esp3d("Processing FS : %s", filename);
if (!ESP_FileSystem::exists(filename)) {
log_esp3d("Cannot find file");
return false;
}
ESP_File f = ESP_FileSystem::open(filename);
if (!f.isOpen()) {
log_esp3d("Cannot open file");
return false;
}
size_t filesize = f.size();
int8_t ch;
String cmd = "";
for (size_t c = 0; c< filesize ; c++) {
ch = f.read();
if (ch == -1) {
log_esp3d("Error reading file");
f.close();
return false;
}
if ((ch == 13)||(ch == 10) || (c==(filesize-1))) {
//for end of file without \n neither \r
if (!((ch == 13)||(ch == 10)) && (c==(filesize-1))) {
cmd+=(char)ch;
}
cmd.trim();
if(cmd.length() > 0) {
//ignore comments
if (cmd[0]!=';') {
//it is internal or not ?
if(esp3d_commands.is_esp_command((uint8_t *)cmd.c_str(), cmd.length())) {
esp3d_commands.process((uint8_t *)cmd.c_str(), cmd.length(), output, auth_type);
} else {
if (!sendCommand(cmd.c_str(),false, true)) {
log_esp3d("Error sending command");
//To stop instead of continue may need some trigger
}
}
}
cmd="";
}
} else {
cmd+=(char)ch;
}
}
f.close();
return res;
}
bool GcodeHost::processFile(const char * filename, level_authenticate_type auth_type, ESP3DOutput * output)
{
String FileName = filename;
FileName.trim();
log_esp3d("Processing: %s", FileName.c_str());
if (FileName.startsWith(ESP_FLASH_FS_HEADER)) {
String f = FileName.substring(strlen(ESP_FLASH_FS_HEADER),FileName.length());
return processFSFile(f.c_str(), auth_type, output);
}
//TODO SD = SDCard
//TODO UD = USB DISK
log_esp3d("Invalid filename");
return false;
}
#endif //ESP_GCODE_HOST_FEATURE

View File

@ -23,6 +23,10 @@
#ifndef _GCODE_HOST_H
#define _GCODE_HOST_H
#include <Arduino.h>
#include "../authentication/authentication_service.h"
class ESP3DOutput;
#define DEFAULT_TIMOUT 2000
#define MAX_TRY_2_SEND 5
#define ERROR_NO_ERROR 0
@ -44,20 +48,34 @@ public:
void end();
void handle();
bool sendCommand(const char* command, bool checksum = false, bool wait4ack = true, const char * ack=nullptr);
uint16_t currentCommandNumber(){return _commandnumber;}
void setCommandNumber(uint16_t n){_commandnumber = n;}
uint32_t currentCommandNumber()
{
return _commandnumber;
}
void setCommandNumber(uint32_t n)
{
_commandnumber = n;
}
bool resetCommandNumbering();
uint8_t Checksum(const char * command, uint16_t commandSize);
String CheckSumCommand(const char* command, uint16_t commandnb);
uint8_t Checksum(const char * command, uint32_t commandSize);
String CheckSumCommand(const char* command, uint32_t commandnb);
size_t wait_for_data(uint32_t timeout = DEFAULT_TIMOUT);
bool wait_for_ack(uint32_t timeout = DEFAULT_TIMOUT, bool checksum=false, const char * ack=nullptr);
bool purge(uint32_t timeout = DEFAULT_TIMOUT);
uint16_t Get_commandNumber(String & response);
bool waitWhenIdle(){ return _waitwhenidle;}
uint8_t getErrorNum(){ return _error;}
uint32_t Get_commandNumber(String & response);
bool waitWhenIdle()
{
return _waitwhenidle;
}
uint8_t getErrorNum()
{
return _error;
}
bool processFile(const char * filename, level_authenticate_type auth_type, ESP3DOutput * output);
bool processFSFile(const char * filename, level_authenticate_type auth_type, ESP3DOutput * output);
private:
uint16_t _commandnumber;
uint16_t _needcommandnumber;
uint32_t _commandnumber;
uint32_t _needcommandnumber;
bool _waitwhenidle;
uint8_t _error;
};