Skip to content

Commit 4d24f4b

Browse files
committed
First working pipe implementation.
1 parent 5f7c00a commit 4d24f4b

File tree

5 files changed

+460
-12
lines changed

5 files changed

+460
-12
lines changed
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
/*
2+
* Created on Oct. 2 2020
3+
*
4+
* Copyright (c) 2020 - Daniel Hajnal
5+
6+
* This file is part of the Shellminator project.
7+
* Modified 2022.10.02
8+
*
9+
*/
10+
11+
#include <WiFi.h>
12+
#include "esp_wifi.h"
13+
14+
#include "Shellminator.hpp"
15+
#include "Shellminator-IO.hpp"
16+
17+
// Necessary includes
18+
#include "Commander-API.hpp"
19+
#include "Commander-IO.hpp"
20+
21+
#define SERVER_PORT 23
22+
23+
// WiFi credentials.
24+
const char* ssid = "WIFI_SSID";
25+
const char* password = "WIFI_PASS";
26+
27+
// Create an instance of the server.
28+
// It will be available on port 23.
29+
WiFiServer server( SERVER_PORT );
30+
31+
// Create a Shellminator object, and initialize it to use WiFiServer
32+
Shellminator shell( &server );
33+
34+
const char logo[] =
35+
36+
" _____ __ ____ _ __ \r\n"
37+
" / ___// /_ ___ / / /___ ___ (_)___ ____ _/ /_____ _____\r\n"
38+
" \\__ \\/ __ \\/ _ \\/ / / __ `__ \\/ / __ \\/ __ `/ __/ __ \\/ ___/\r\n"
39+
" ___/ / / / / __/ / / / / / / / / / / / /_/ / /_/ /_/ / / \r\n"
40+
"/____/_/ /_/\\___/_/_/_/ /_/ /_/_/_/ /_/\\__,_/\\__/\\____/_/ \r\n"
41+
" \r\n"
42+
;
43+
44+
// We have to create an object from Commander class.
45+
Commander commander;
46+
47+
// We have to create the prototype functions for our commands.
48+
// The arguments has to be the same for all command functions.
49+
void cat_func( char *args, Stream *response );
50+
void dog_func( char *args, Stream *response );
51+
void sum_func( char *args, Stream *response );
52+
void led_func( char *args, Stream *response );
53+
void ledPWM_func( char *args, Stream *response );
54+
void random_func( char *args, Stream *response );
55+
56+
// Commander API-tree
57+
Commander::API_t API_tree[] = {
58+
apiElement( "cat", "Description for cat command.", cat_func ),
59+
apiElement( "dog", "Description for dog command.", dog_func ),
60+
apiElement( "led", "Toggle the buit-in LED.", led_func ),
61+
apiElement( "sum", "This function sums two number from the argument list.", sum_func ),
62+
apiElement( "ledPWM", "Set the brightness of the LED", ledPWM_func ),
63+
apiElement( "random", "Generate a random number between the arguments.", random_func )
64+
};
65+
66+
void setup() {
67+
68+
// Initialize Serial with 115200 baudrate.
69+
Serial.begin( 115200 );
70+
71+
// If you using Atmega32U4, the code will wait, until
72+
// you open the serial port.
73+
while( !Serial );
74+
75+
// Clear the terminal
76+
shell.clear();
77+
78+
// Attach the logo.
79+
shell.attachLogo( logo );
80+
81+
// Print start message
82+
Serial.println( "Program begin..." );
83+
84+
// WiFi configuration section
85+
Serial.print( "Connect to WiFi: " );
86+
Serial.print( ssid );
87+
88+
WiFi.mode( WIFI_STA );
89+
WiFi.setSleep(WIFI_PS_NONE);
90+
WiFi.begin( ssid, password );
91+
92+
while( WiFi.status() != WL_CONNECTED ){
93+
94+
delay( 1000 );
95+
Serial.print( "." );
96+
97+
}
98+
99+
shell.beginServer();
100+
101+
Serial.println( " [ OK ]" );
102+
103+
Serial.println( "Connected!" );
104+
Serial.print( "Device IP: " );
105+
Serial.print( WiFi.localIP() );
106+
Serial.print( " at port: " );
107+
Serial.println( SERVER_PORT );
108+
109+
110+
// There is an option to attach a debug channel to Commander.
111+
// It can be handy to find any problems during the initialization
112+
// phase. In this example we will use Serial for this.
113+
commander.attachDebugChannel( &Serial );
114+
115+
// At start, Commander does not know anything about our commands.
116+
// We have to attach the API_tree array from the previous steps
117+
// to Commander to work properly.
118+
commander.attachTree( API_tree );
119+
120+
// Initialize Commander.
121+
commander.init();
122+
123+
shell.attachCommander( &commander );
124+
125+
// initialize shell object.
126+
shell.begin( "arnold" );
127+
128+
}
129+
130+
void loop() {
131+
132+
shell.update();
133+
134+
}
135+
136+
/// This is an example function for the cat command
137+
void cat_func(char *args, Stream *response )
138+
{
139+
140+
response -> print("Hello from cat function!\r\n");
141+
142+
}
143+
144+
/// This is an example function for the dog command
145+
void dog_func(char *args, Stream *response )
146+
{
147+
148+
response -> print("Hello from dog function!\r\n");
149+
150+
}
151+
152+
/// This is an example function for the led command
153+
void led_func(char *args, Stream *response )
154+
{
155+
156+
// Toggle your LED pin here, if you have on your board
157+
// digitalWrite( LED_PIN, !digitalRead( LED_PIN ) );
158+
response -> print("LED toggle!\r\n");
159+
160+
}
161+
162+
/// This is an example function for the sum command
163+
void sum_func(char *args, Stream *response )
164+
{
165+
166+
// These variables will hold the value of the
167+
// two numbers, that has to be summed.
168+
int a = 0;
169+
int b = 0;
170+
171+
// This variable will hold the result of the
172+
// argument parser.
173+
int argResult;
174+
175+
// This variable will hold the sum result.
176+
int sum = 0;
177+
178+
argResult = sscanf( args, "%d %d", &a, &b );
179+
180+
// We have to check that we parsed successfully the two
181+
// numbers from the argument string.
182+
if( argResult != 2 ){
183+
184+
// If we could not parse two numbers, we have an argument problem.
185+
// We print out the problem to the response channel.
186+
response -> print( "Argument error! Two numbers required, separated with a blank space.\r\n" );
187+
188+
// Sadly we have to stop the command execution and return.
189+
return;
190+
191+
}
192+
193+
// Calculate the sum.
194+
sum = a + b;
195+
196+
// Print out the result.
197+
response -> print( a );
198+
response -> print( " + " );
199+
response -> print( b );
200+
response -> print( " = " );
201+
response -> println( sum );
202+
203+
}
204+
205+
void ledPWM_func(char *args, Stream *response ){
206+
207+
int pwm = 0;
208+
209+
int argResult;
210+
211+
argResult = sscanf( args, "%d", &pwm );
212+
213+
if( argResult != 1 ){
214+
215+
response -> print( "Argument error!" );
216+
217+
// Sadly we have to stop the command execution and return.
218+
return;
219+
220+
}
221+
222+
if( pwm > 100 ){
223+
pwm = 100;
224+
}
225+
226+
if( pwm < 0 ){
227+
pwm = 0;
228+
}
229+
230+
response -> print( "New PWM value: " );
231+
response -> print( pwm );
232+
233+
}
234+
235+
void random_func(char *args, Stream *response ){
236+
237+
int minVal;
238+
int maxVal;
239+
240+
int argResult;
241+
242+
argResult = sscanf( args, "%d %d", &minVal, &maxVal );
243+
244+
if( argResult != 2 ){
245+
246+
response -> print( "Argument error!" );
247+
248+
// Sadly we have to stop the command execution and return.
249+
return;
250+
251+
}
252+
253+
response -> print( random( minVal, maxVal ) );
254+
255+
}

src/Commander-API.cpp

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,8 @@ void Commander::executeCommand( char *cmd ){
299299

300300
int32_t pipePos;
301301

302+
uint32_t i;
303+
302304
// Copy the command data to the internal buffer.
303305
// It is necessary because we have to modify the content
304306
// of it. If it is points to a const char array we will
@@ -307,6 +309,13 @@ void Commander::executeCommand( char *cmd ){
307309

308310
pipePos = hasChar( tempBuff, '|' );
309311

312+
if( pipePos >= 0 ){
313+
314+
// Terminate where pip is found.
315+
tempBuff[ pipePos ] = '\0';
316+
317+
}
318+
310319
// tempBuff is the address of the first character of the incoming command.
311320
// If we give arg variable the value stored in tempBuff means arg will point to
312321
// the first character of the command as well.
@@ -344,13 +353,6 @@ void Commander::executeCommand( char *cmd ){
344353

345354
}
346355

347-
else if( *arg == '|' ){
348-
349-
*arg = '\0';
350-
arg++;
351-
352-
}
353-
354356
// Try to find the command datata.
355357
commandData_ptr = (*this)[ tempBuff ];
356358

@@ -392,16 +394,66 @@ void Commander::executeCommand( char *cmd ){
392394
// If show_description flag is not set, than we have to execute the commands function.
393395
else{
394396

397+
// TODO if the pipe buffer has data, the arg has to be replaced with that.
398+
if( pipeChannel.available() > 0 ){
399+
400+
// pipeChannel.readBytesUntil( '\0', pipeArgBuffer, COMMANDER_MAX_COMMAND_SIZE );
401+
402+
i = 0;
403+
404+
while( pipeChannel.available() ){
405+
406+
if( i < COMMANDER_MAX_COMMAND_SIZE ){
407+
408+
pipeArgBuffer[ i ] = pipeChannel.read();
409+
410+
}
411+
412+
else{
413+
414+
pipeChannel.read();
415+
416+
}
417+
418+
i++;
419+
420+
}
421+
422+
if( i < COMMANDER_MAX_COMMAND_SIZE ){
423+
424+
pipeArgBuffer[ i ] = '\0';
425+
426+
}
427+
428+
pipeArgBuffer[ COMMANDER_MAX_COMMAND_SIZE - 1 ] = '\0';
429+
430+
arg = pipeArgBuffer;
431+
432+
}
433+
395434
if( pipePos > 0 ){
396435

397-
// TODO Switch response to internal buffer.
436+
// Execute commands function and redirect the output to pipe.
437+
(commandData_ptr -> func)( arg, &pipeChannel );
438+
439+
}
440+
441+
else{
442+
443+
(commandData_ptr -> func)( arg, response );
398444

399445
}
400446

401-
// TODO if the internal buffer has data, the arg has to be replaced to that.
447+
if( pipePos > 0 ){
448+
449+
// To remowe whitespace from the new command begin.
450+
while( tempBuff[ pipePos + 1 ] == ' ' ){
451+
pipePos++;
452+
}
453+
454+
executeCommand( &tempBuff[ pipePos + 1 ] );
402455

403-
// Execute commands function.
404-
(commandData_ptr -> func)( arg, response );
456+
}
405457

406458
}
407459

@@ -444,6 +496,13 @@ void Commander::executeCommand( char *cmd ){
444496

445497
#endif
446498

499+
// Clear the pipe at error.
500+
while( pipeChannel.available() ){
501+
502+
pipeChannel.read();
503+
504+
}
505+
447506
}
448507

449508
}

src/Commander-API.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,8 @@ class Commander{
310310

311311
int32_t hasChar( char* str, char c );
312312

313-
char pipeBuffer[COMMANDER_MAX_COMMAND_SIZE];
313+
commanderPipeChannel pipeChannel;
314+
char pipeArgBuffer[ COMMANDER_MAX_COMMAND_SIZE ];
314315

315316
};
316317

0 commit comments

Comments
 (0)