A web server for monitoring and controlling a MakerBot Replicator over the USB host and ethernet.
Dependencies: IAP NTPClient RTC mbed-rtos mbed Socket lwip-sys lwip BurstSPI
Fork of LPC1768_Mini-DK by
telnetd.cpp
00001 // Copyright (c) 2013, jake (at) allaboutjake (dot) com 00002 // All rights reserved. 00003 // 00004 // Redistribution and use in source and binary forms, with or without 00005 // modification, are permitted provided that the following conditions are met: 00006 // * Redistributions of source code must retain the above copyright 00007 // notice, this list of conditions and the following disclaimer. 00008 // * Redistributions in binary form must reproduce the above copyright 00009 // notice, this list of conditions and the following disclaimer in the 00010 // documentation and/or other materials provided with the distribution. 00011 // * The name of the author and/or copyright holder nor the 00012 // names of its contributors may be used to endorse or promote products 00013 // derived from this software without specific prior written permission. 00014 // 00015 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00016 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00017 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00018 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, AUTHOR, OR ANY CONTRIBUTORS 00019 // BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00020 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00021 // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00022 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00023 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00024 // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00025 00026 // DESCRIPTION OF FILE: 00027 // 00028 // This file contains a simple telnet server on port 7654. The main function is 00029 // "telnet_server_task" which is intended to be run in a thread after the 00030 // network (EthernetInterface) bas been configured. 00031 #include "mbed.h" 00032 #include "main.h" 00033 #include "telnetd.h" 00034 #include "EthernetInterface.h" 00035 #include "SimpleSocket.h" 00036 #include "readline.h" 00037 #include "settings.h" 00038 00039 int readline_password(ClientSocket* socket, char* buffer, int max_length); 00040 00041 // Network server task: setup and listen for network connections 00042 void telnet_server_task(void const*) { 00043 // This thread assumes that the EthernetInterface is connected with an IP address. 00044 static int TELNET_PORT = 7654; 00045 00046 //Use SimpleSocket library to setup a server socket 00047 ServerSocket serverSocket(TELNET_PORT); 00048 00049 while (1) { 00050 ClientSocket socket = serverSocket.accept(); 00051 00052 //Create buffer to hold the command prompt input and filename 00053 char promptBuffer[MAX_PROMPT_BUFFER_SIZE]; 00054 00055 char* token = getAuthenticationToken(); 00056 if (token != NULL) { 00057 int authLen = readline_password(&socket, promptBuffer, MAX_PROMPT_BUFFER_SIZE); 00058 if (memcmp(promptBuffer, token, authLen) != 0) { 00059 socket.printf("Authentication failed\r\n"); 00060 socket.close(); 00061 continue; 00062 } 00063 } 00064 00065 //Main loop 00066 while (1) { 00067 // Print the prompt 00068 socket.printf("> "); 00069 00070 // Get the command 00071 int cmdLength = readline(&socket, promptBuffer, MAX_PROMPT_BUFFER_SIZE); 00072 00073 if (cmdLength > 0) { 00074 switch(promptBuffer[0]) { 00075 case 'A': 00076 case 'a': 00077 { 00078 int tokenLength = cmdLength - 2; 00079 if (tokenLength > 1) { 00080 setAuthenticationToken(promptBuffer+2, tokenLength); 00081 char* token = getAuthenticationToken(); 00082 socket.printf("Authentication set to: %s\r\n", token); 00083 } else { 00084 socket.printf("Command usage: A <username>:<password> - set authentication username/password\r\n"); 00085 } 00086 break; 00087 } 00088 00089 case 'B': 00090 case 'b': 00091 //BUILD command - make sure there's a space between cmd and filename 00092 if (cmdLength > 1 && promptBuffer[1]==' ') { 00093 int fileNameLength = cmdLength - 2; 00094 //make sure the filename is at least 5 characters (minimally "?.X3G") 00095 if (fileNameLength >= 5) { 00096 // Check for X3G extension. 00097 if (memcmp(promptBuffer+cmdLength-4, ".X3G", 4)==0 || 00098 memcmp(promptBuffer+cmdLength-4, ".x3g", 4)==0) { 00099 // Copy filename into filename buffer 00100 char filename[13]; 00101 strncpy(filename, promptBuffer+2, cmdLength-2); 00102 filename[cmdLength-2]='\0';//terminate 00103 00104 //Print the message to the display and the serial console 00105 DISPLAY("Printing filename: '%s'\r\n", filename); 00106 socket.printf("Printing filename: '%s'\r\n", filename); 00107 00108 //Send command to bot to print 00109 if (bot) { 00110 bot->playbackCapture(filename); 00111 } else { 00112 socket.printf("Error: connection to Makerbot not established.\r\n"); 00113 } 00114 } else { 00115 socket.printf("Error: filename doesn't end with X3G\r\n"); 00116 } 00117 } else { 00118 socket.printf("Error: filename must be 5-12 characters long\r\n"); 00119 } 00120 } else { 00121 socket.printf("Command usage: B <filename.X3G> - begin build (8.3 filename)\r\n"); 00122 00123 } 00124 break; 00125 case 'C': 00126 case 'c': 00127 if (bot) { 00128 bot->abortImmediately(); 00129 socket.printf("Cancelling build.\r\n"); 00130 } else { 00131 socket.printf("Error: connection to Makerbot not established.\r\n"); 00132 } 00133 break; 00134 00135 case 'P': 00136 case 'p': 00137 if (bot) { 00138 Makerbot::MakerbotBuildState state = bot->getBuildState(); 00139 if (state.build_state == Makerbot::BUILD_STATE_ERROR) { 00140 socket.printf("Error: unable to determine build state. Sending pause/resume command in the blind.\r\n"); 00141 bot->pauseResume(); 00142 } else if (state.build_state == Makerbot::BUILD_RUNNING) { 00143 bot->pauseResume(); 00144 socket.printf("Pausing build.\r\n"); 00145 } else { 00146 socket.printf("Error: Not currently building, cannot pause\r\n"); 00147 } 00148 } else { 00149 socket.printf("Error: connection to Makerbot not established.\r\n"); 00150 } 00151 break; 00152 00153 case 'R': 00154 case 'r': 00155 if (bot) { 00156 Makerbot::MakerbotBuildState state = bot->getBuildState(); 00157 if (state.build_state == Makerbot::BUILD_STATE_ERROR) { 00158 socket.printf("Error: unable to determine build state. Sending pause/resume command in the blind.\r\n"); 00159 bot->pauseResume(); 00160 } else if (state.build_state == Makerbot::BUILD_PAUSED) { 00161 bot->pauseResume(); 00162 socket.printf("Pausing build.\r\n"); 00163 } else { 00164 socket.printf("Error: Not currently paused. Cannot resume.\r\n"); 00165 } 00166 } else { 00167 socket.printf("Error: connection to Makerbot not established.\r\n"); 00168 } 00169 break; 00170 00171 case 'S': 00172 case 's': 00173 if (bot) { 00174 Makerbot::MakerbotBuildState state = bot->getBuildState(); 00175 socket.printf("Build State: %s\r\n", Makerbot::humanReadableBuildState(state)); 00176 socket.printf("\tElapsed build time: %d:%02d\r\n", state.hours, state.minutes); 00177 socket.printf("\tLine #: %ld\r\n", state.line); 00178 00179 for (int x=0; x<bot->getToolCount(); x++) { 00180 socket.printf("\tTool %d: %dºc/%dºc\r\n", x, bot->getToolTemperature(x), bot->getToolSetPoint(x)); 00181 } 00182 socket.printf("\tPlatform %dºc/%dºc\r\n", bot->getPlatformTemperature(0), bot->getPlatformSetPoint(0)); 00183 00184 } 00185 break; 00186 00187 case 'Q': 00188 case 'q': 00189 socket.printf("Logging out\r\n"); 00190 socket.close(); 00191 break; 00192 00193 case 'v': 00194 case 'V': 00195 if (bot) { 00196 char* bot_name = bot->getMachineName(); 00197 socket.printf("Machine name: %s\r\n", bot_name); 00198 00199 float version = bot->getMakerbotVersion(); 00200 socket.printf("Makerbot version: %0.1f\r\n", version); 00201 socket.printf("Local firmware version: %s\r\n", FIRMWARE_VERSION); 00202 } else { 00203 socket.printf("Error: connection to Makerbot not established.\r\n"); 00204 } 00205 break; 00206 default: 00207 socket.printf("unknown command\r\n"); 00208 } 00209 } 00210 Thread::wait(100); 00211 00212 // Go back around and wait for a new connection if we've disconnected 00213 if (!socket.connected()) 00214 break; 00215 } 00216 } 00217 // never gets here 00218 //EthernetInterface::disconnect(); 00219 } 00220 00221 //Readline routine customized to return a "username:password" style string 00222 int readline_password(ClientSocket* socket, char* buffer, int max_length) { 00223 int curPos = 0; 00224 int usernamePasswordStep = 0; 00225 socket->printf("user: "); 00226 00227 while (1) { 00228 int c; 00229 00230 //Wait for a character 00231 while ((c=socket->read()) < 0) { 00232 if (!socket->connected()) return -1; 00233 Thread::yield(); 00234 } 00235 00236 switch (c) { 00237 case '\r': 00238 continue; 00239 00240 case '\b': 00241 if (curPos > 0) curPos--; 00242 break; 00243 00244 default: 00245 buffer[curPos]= (char)(c & 0xFF); 00246 curPos++; 00247 if (curPos < max_length) 00248 break; 00249 00250 //FALLTHROUGH 00251 case '\n': 00252 if (usernamePasswordStep==0) { 00253 socket->printf("password: "); 00254 buffer[curPos] = ':'; 00255 curPos++; 00256 usernamePasswordStep++; 00257 break; 00258 } else { 00259 socket->printf("\r\n"); 00260 buffer[curPos]=0x00; //string terminator 00261 return curPos; 00262 } 00263 } 00264 } 00265 00266 }
Generated on Tue Jul 12 2022 17:52:03 by 1.7.2