Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
SimpleShell.cpp
00001 /* 00002 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl). 00003 Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 00004 Smoothie 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 General Public License for more details. 00005 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 00006 */ 00007 00008 00009 #include "libs/Kernel.h" 00010 #include "SimpleShell.h" 00011 #include "libs/nuts_bolts.h" 00012 #include "libs/utils.h" 00013 #include "libs/SerialMessage.h" 00014 #include "libs/StreamOutput.h" 00015 #include "modules/robot/Player.h" 00016 00017 00018 void SimpleShell::on_module_loaded(){ 00019 this->current_path = "/"; 00020 this->playing_file = false; 00021 this->register_for_event(ON_CONSOLE_LINE_RECEIVED); 00022 this->register_for_event(ON_MAIN_LOOP); 00023 } 00024 00025 // When a new line is received, check if it is a command, and if it is, act upon it 00026 void SimpleShell::on_console_line_received( void* argument ){ 00027 SerialMessage new_message = *static_cast<SerialMessage*>(argument); 00028 string possible_command = new_message.message; 00029 00030 // We don't compare to a string but to a checksum of that string, this saves some space in flash memory 00031 unsigned short check_sum = get_checksum( possible_command.substr(0,possible_command.find_first_of(" \r\n")) ); // todo: put this method somewhere more convenient 00032 00033 // Act depending on command 00034 switch( check_sum ){ 00035 case ls_command_checksum : this->ls_command( get_arguments(possible_command), new_message.stream ); break; 00036 case cd_command_checksum : this->cd_command( get_arguments(possible_command), new_message.stream ); break; 00037 case pwd_command_checksum : this->pwd_command( get_arguments(possible_command), new_message.stream ); break; 00038 case cat_command_checksum : this->cat_command( get_arguments(possible_command), new_message.stream ); break; 00039 case play_command_checksum : this->play_command(get_arguments(possible_command), new_message.stream ); break; 00040 case reset_command_checksum : this->reset_command(get_arguments(possible_command),new_message.stream ); break; 00041 } 00042 } 00043 00044 // Convert a path indication ( absolute or relative ) into a path ( absolute ) 00045 string SimpleShell::absolute_from_relative( string path ){ 00046 if( path[0] == '/' ){ return path; } 00047 if( path[0] == '.' ){ return this->current_path; } 00048 return this->current_path + path; 00049 } 00050 00051 // Act upon an ls command 00052 // Convert the first parameter into an absolute path, then list the files in that path 00053 void SimpleShell::ls_command( string parameters, StreamOutput* stream ){ 00054 string folder = this->absolute_from_relative( parameters ); 00055 DIR* d; 00056 struct dirent* p; 00057 d = opendir(folder.c_str()); 00058 if(d != NULL) { 00059 while((p = readdir(d)) != NULL) { stream->printf("%s\r\n", lc(string(p->d_name)).c_str()); } 00060 } else { 00061 stream->printf("Could not open directory %s \r\n", folder.c_str()); 00062 } 00063 } 00064 00065 // Change current absolute path to provided path 00066 void SimpleShell::cd_command( string parameters, StreamOutput* stream ){ 00067 string folder = this->absolute_from_relative( parameters ); 00068 if( folder[folder.length()-1] != '/' ){ folder += "/"; } 00069 DIR *d; 00070 struct dirent *p; 00071 d = opendir(folder.c_str()); 00072 if(d == NULL) { 00073 stream->printf("Could not open directory %s \r\n", folder.c_str() ); 00074 }else{ 00075 this->current_path = folder; 00076 } 00077 } 00078 00079 // Responds with the present working directory 00080 void SimpleShell::pwd_command( string parameters, StreamOutput* stream ){ 00081 stream->printf("%s\r\n", this->current_path.c_str()); 00082 } 00083 00084 // Output the contents of a file, first parameter is the filename, second is the limit ( in number of lines to output ) 00085 void SimpleShell::cat_command( string parameters, StreamOutput* stream ){ 00086 00087 // Get parameters ( filename and line limit ) 00088 string filename = this->absolute_from_relative(shift_parameter( parameters )); 00089 string limit_paramater = shift_parameter( parameters ); 00090 int limit = -1; 00091 if( limit_paramater != "" ){ limit = int(atof(limit_paramater.c_str())); } 00092 00093 // Open file 00094 FILE *lp = fopen(filename.c_str(), "r"); 00095 if(lp == NULL) { 00096 stream->printf("File not found: %s\r\n", filename.c_str()); 00097 return; 00098 } 00099 string buffer; 00100 int c; 00101 int newlines = 0; 00102 00103 // Print each line of the file 00104 while ((c = fgetc (lp)) != EOF){ 00105 buffer.append((char *)&c, 1); 00106 if( char(c) == '\n' ){ 00107 newlines++; 00108 stream->printf("%s", buffer.c_str()); 00109 buffer.clear(); 00110 } 00111 if( newlines == limit ){ break; } 00112 }; 00113 fclose(lp); 00114 00115 } 00116 00117 // Play a gcode file by considering each line as if it was received on the serial console 00118 void SimpleShell::play_command( string parameters, StreamOutput* stream ){ 00119 // Get filename 00120 string filename = this->absolute_from_relative(shift_parameter( parameters )); 00121 this->current_file_handler = fopen( filename.c_str(), "r"); 00122 if(this->current_file_handler == NULL) 00123 { 00124 stream->printf("File not found: %s\r\n", filename.c_str()); 00125 return; 00126 } 00127 this->playing_file = true; 00128 this->current_stream = stream; 00129 } 00130 00131 // Reset the system 00132 void SimpleShell::reset_command( string parameters, StreamOutput* stream){ 00133 stream->printf("Smoothie out. Peace.\r\n"); 00134 system_reset(); 00135 } 00136 00137 void SimpleShell::on_main_loop(void* argument){ 00138 00139 if( this->playing_file ){ 00140 string buffer; 00141 int c; 00142 // Print each line of the file 00143 while ((c = fgetc(this->current_file_handler)) != EOF){ 00144 if (c == '\n'){ 00145 this->current_stream->printf("%s\n", buffer.c_str()); 00146 struct SerialMessage message; 00147 message.message = buffer; 00148 message.stream = this->current_stream; 00149 // wait for the queue to have enough room that a serial message could still be received before sending 00150 this->kernel->player->wait_for_queue(2); 00151 this->kernel->call_event(ON_CONSOLE_LINE_RECEIVED, &message); 00152 buffer.clear(); 00153 return; 00154 }else{ 00155 buffer += c; 00156 } 00157 }; 00158 00159 fclose(this->current_file_handler); 00160 this->playing_file = false; 00161 } 00162 }
Generated on Tue Jul 12 2022 14:14:41 by
1.7.2