From c03418dc3c8781fd0e3ca369670379c66960c951 Mon Sep 17 00:00:00 2001 From: Rob Newton Date: Sun, 21 Dec 2014 22:11:28 -0500 Subject: [PATCH] Added processCharacter method Separated buffer building and command parsing from serial port reading. --- SerialCommand.cpp | 104 ++++++++++++++++++++++++++-------------------- SerialCommand.h | 1 + 2 files changed, 59 insertions(+), 46 deletions(-) diff --git a/SerialCommand.cpp b/SerialCommand.cpp index bbea5ba..152db4a 100644 --- a/SerialCommand.cpp +++ b/SerialCommand.cpp @@ -2,11 +2,12 @@ * SerialCommand - A Wiring/Arduino library to tokenize and parse commands * received over a serial port. * + * Copyright (C) 2014 Rob Newton * Copyright (C) 2012 Stefan Rado * Copyright (C) 2011 Steven Cogswell * http://husks.wordpress.com * - * Version 20120522 + * Version 20141221 * * 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 @@ -66,67 +67,78 @@ void SerialCommand::setDefaultHandler(void (*function)(const char *)) { /** - * This checks the Serial stream for characters, and assembles them into a buffer. + * Accepts a character as a parameter intended to be called in a loop passing + * multiple characters that it assembles into a buffer. By breaking the command + * parsing out of readSerial, it allows callers to get the data from anywhere. * When the terminator character (default '\n') is seen, it starts parsing the * buffer for a prefix command, and calls handlers setup by addCommand() member */ -void SerialCommand::readSerial() { - while (Serial.available() > 0) { - char inChar = Serial.read(); // Read single available character, there may be more waiting +void SerialCommand::processCharacter(char inChar) { + #ifdef SERIALCOMMAND_DEBUG + Serial.print(inChar); // Echo back to serial stream + #endif + + if (inChar == term) { // Check for the terminator (default '\r') meaning end of command #ifdef SERIALCOMMAND_DEBUG - Serial.print(inChar); // Echo back to serial stream + Serial.print("Received: "); + Serial.println(buffer); #endif - if (inChar == term) { // Check for the terminator (default '\r') meaning end of command + char *command = strtok_r(buffer, delim, &last); // Search for command at start of buffer + if (command != NULL) { + boolean matched = false; + for (int i = 0; i < commandCount; i++) { #ifdef SERIALCOMMAND_DEBUG - Serial.print("Received: "); - Serial.println(buffer); + Serial.print("Comparing ["); + Serial.print(command); + Serial.print("] to ["); + Serial.print(commandList[i].command); + Serial.println("]"); #endif - char *command = strtok_r(buffer, delim, &last); // Search for command at start of buffer - if (command != NULL) { - boolean matched = false; - for (int i = 0; i < commandCount; i++) { - #ifdef SERIALCOMMAND_DEBUG - Serial.print("Comparing ["); - Serial.print(command); - Serial.print("] to ["); - Serial.print(commandList[i].command); - Serial.println("]"); - #endif - - // Compare the found command against the list of known commands for a match - if (strncmp(command, commandList[i].command, SERIALCOMMAND_MAXCOMMANDLENGTH) == 0) { - #ifdef SERIALCOMMAND_DEBUG - Serial.print("Matched Command: "); - Serial.println(command); - #endif + // Compare the found command against the list of known commands for a match + if (strncmp(command, commandList[i].command, SERIALCOMMAND_MAXCOMMANDLENGTH) == 0) { + #ifdef SERIALCOMMAND_DEBUG + Serial.print("Matched Command: "); + Serial.println(command); + #endif - // Execute the stored handler function for the command - (*commandList[i].function)(); - matched = true; - break; - } - } - if (!matched && (defaultHandler != NULL)) { - (*defaultHandler)(command); - } + // Execute the stored handler function for the command + (*commandList[i].function)(); + matched = true; + break; } - clearBuffer(); } - else if (isprint(inChar)) { // Only printable characters into the buffer - if (bufPos < SERIALCOMMAND_BUFFER) { - buffer[bufPos++] = inChar; // Put character into buffer - buffer[bufPos] = '\0'; // Null terminate - } else { - #ifdef SERIALCOMMAND_DEBUG - Serial.println("Line buffer is full - increase SERIALCOMMAND_BUFFER"); - #endif - } + if (!matched && (defaultHandler != NULL)) { + (*defaultHandler)(command); + } + } + clearBuffer(); + } + else if (isprint(inChar)) { // Only printable characters into the buffer + if (bufPos < SERIALCOMMAND_BUFFER) { + buffer[bufPos++] = inChar; // Put character into buffer + buffer[bufPos] = '\0'; // Null terminate + } else { + #ifdef SERIALCOMMAND_DEBUG + Serial.println("Line buffer is full - increase SERIALCOMMAND_BUFFER"); + #endif } } } + +/** + * This checks the Serial stream for characters, and assembles them into a buffer + * by calling processCharacter for each character received over the serial line. + */ +void SerialCommand::readSerial() { + while (Serial.available() > 0) { + char inChar = Serial.read(); // Read single available character, there may be more waiting + processCharacter(inChar); + } +} + /* * Clear the input buffer. */ diff --git a/SerialCommand.h b/SerialCommand.h index e00dd29..96fa88e 100644 --- a/SerialCommand.h +++ b/SerialCommand.h @@ -48,6 +48,7 @@ class SerialCommand { void addCommand(const char *command, void(*function)()); // Add a command to the processing dictionary. void setDefaultHandler(void (*function)(const char *)); // A handler to call when no valid command received. + void processCharacter(char inChar); // Accumulate a command by calling this for each character of it void readSerial(); // Main entry point. void clearBuffer(); // Clears the input buffer. char *next(); // Returns pointer to next token found in command buffer (for getting arguments to commands).