Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# SerialCommands
# SerialCommands - MODIFIED
This is a fork that allows you to inject arbitrary commands as if they were typed at the serial console. Useful if you want to use SerialCommands as a central dispatch for quick n dirty message processing from external sources (like MQTT/HTTP/etc)

An Arduino library to tokenize and parse commands received over a serial port.

Inspired by (original version):
Expand Down
6 changes: 3 additions & 3 deletions library.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
"name": "SerialCommands",
"authors":
{
"name": "Pedro Tiago Pereira",
"name": "Pedro Tiago Pereira (Original Author)",
"email": "tiago.private@gmail.com",
"url": "https://github.com/ppedro74"
},
"keywords": "serial, command, commands, cmd, parse, callback",
"description": "A Library to tokenize and parse commands received over a serial port. Simple and small memory footprint (no dynamic memory allocation)",
"description": "[forked] A Library to tokenize and parse commands received over a serial port. Simple and small memory footprint (no dynamic memory allocation)",
"repository":
{
"type": "git",
"url": "https://github.com/ppedro74/Arduino-SerialCommands.git"
"url": "https://github.com/binary1230/Arduino-SerialCommands.git"
},
"version": "2.2.0",
"frameworks": "arduino",
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ maintainer=Pedro Tiago Pereira <tiago.private@gmail.com>
sentence=An Arduino library to tokenize and parse commands received over a serial port.
paragraph=Simple, small footprint, no dynamic memory allocation
category=Data Processing
url=https://github.com/ppedro74/Arduino-SerialCommands
url=https://github.com/binary1230/Arduino-SerialCommands
architectures=*
118 changes: 80 additions & 38 deletions src/SerialCommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,50 +107,92 @@ SERIAL_COMMANDS_ERRORS SerialCommands::ReadSerial()
if (term_[++term_pos_] == 0)
{
buffer_[buffer_pos_ - strlen(term_)] = '\0';
ProcessBuffer();
}
}

#ifdef SERIAL_COMMANDS_DEBUG
Serial.print("Received: [");
Serial.print(buffer_);
Serial.println("]");
#endif
char* command = strtok_r(buffer_, delim_, &last_token_);
if (command != NULL)
{
boolean matched = false;
int cx;
SerialCommand* cmd;
for (cmd = commands_head_, cx = 0; cmd != NULL; cmd = cmd->next, cx++)
{
#ifdef SERIAL_COMMANDS_DEBUG
Serial.print("Comparing [");
Serial.print(command);
Serial.print("] to [");
Serial.print(cmd->command);
Serial.println("]");
#endif
return SERIAL_COMMANDS_SUCCESS;
}

if (strncmp(command, cmd->command, strlen(cmd->command) + 1) == 0)
{
#ifdef SERIAL_COMMANDS_DEBUG
Serial.print("Matched #");
Serial.println(cx);
#endif
cmd->function(this);
matched = true;
break;
}
}
if (!matched && default_handler_ != NULL)
{
(*default_handler_)(this, command);
}
}
void SerialCommands::ProcessBuffer()
{
#ifdef SERIAL_COMMANDS_DEBUG
Serial.print("Received: [");
Serial.print(buffer_);
Serial.println("]");
#endif

ClearBuffer();
char* command = strtok_r(buffer_, delim_, &last_token_);
if (command == NULL) {
ClearBuffer();
return;
}

boolean matched = false;
int cx;
SerialCommand* cmd;
for (cmd = commands_head_, cx = 0; cmd != NULL; cmd = cmd->next, cx++)
{
#ifdef SERIAL_COMMANDS_DEBUG
Serial.print("Comparing [");
Serial.print(command);
Serial.print("] to [");
Serial.print(cmd->command);
Serial.println("]");
#endif

if (strncmp(command, cmd->command, strlen(cmd->command) + 1) == 0)
{
#ifdef SERIAL_COMMANDS_DEBUG
Serial.print("Matched #");
Serial.println(cx);
#endif
cmd->function(this);
matched = true;
break;
}
}
if (!matched && default_handler_ != NULL)
{
(*default_handler_)(this, command);
}

return SERIAL_COMMANDS_SUCCESS;
ClearBuffer();
}

// instead of reading from serial input, manually process this line as if it was sent
// on the serial input. only works for non-OneKey commands.
// any previous buffer is discarded, any in-progress parsing is restarted.
// do not call from inside another command handler.
bool SerialCommands::ProcessCommandLine(const char* line)
{
if (!line || strlen(line) == 0)
return false; // invalid input

if (strlen(line) >= buffer_len_-1)
return false; // not enough buffer space to copy into

// lock so we can't accidentally be called from a command handler
// strtok uses global state and weird recursive calls could potentially mess it up.
// if you do need this capability, this can be rewritten to deal with it.
if (is_processing_cmdline_)
return false;
is_processing_cmdline_ = true; // locked

// clear out anything in progress on the real serial input
// (warning: discards any serial input already typed)
ClearBuffer();

// copy in our line string into the buffer, which is same as what reading from Serial does
strncpy(buffer_, line, buffer_len_ - 1);
buffer_[buffer_len_ - 1] = '\0'; // ensure null-term no matter what

// process the buffer like as though it was recieved via serial input
ProcessBuffer();

is_processing_cmdline_ = false; // unlock

return true;
}

bool SerialCommands::CheckOneKeyCmd()
Expand Down
19 changes: 18 additions & 1 deletion src/SerialCommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ class SerialCommands
onek_cmds_head_(NULL),
onek_cmds_tail_(NULL),
commands_count_(0),
onek_cmds_count_(0)
onek_cmds_count_(0),
is_processing_cmdline_(false)
{
}

Expand Down Expand Up @@ -107,6 +108,19 @@ class SerialCommands
*/
char* Next();

/**
* \brief Alternative input processing: Treat 'line' as if it was received from the Serial input.
* NOTE: Do NOT call this from inside any command handler, it will return false
* This disregards anything currently being typed in via real serial, and clears the buffer afterwards.
* Will not call OneKey commands, only regular commands.
* 'line' must be a null-terminated string
* it should be no more than the initial buffer size minus 1
* 'line' should not end in any delimiters (like newline/etc), just type the string you want.
* example: ProcessCommandLine("set wifi_ssid my_network_name");
* \ return True if successful, false if error (string too low, buffer too small to hold command, or, recursive call detected from cmd handler)
*/
bool ProcessCommandLine(const char* line);

private:
Stream* serial_;
char* buffer_;
Expand All @@ -123,13 +137,16 @@ class SerialCommands
SerialCommand* onek_cmds_tail_;
uint8_t commands_count_;
uint8_t onek_cmds_count_;
bool is_processing_cmdline_;

/**
* \brief Tests for any one_key command and execute it if found
* \return false if this was not a one_key command, true otherwise with
* also clearing the buffer
**/
bool CheckOneKeyCmd();

void ProcessBuffer();
};

#endif