Alt text

InputHandler README#

It’s easy to start using

Check out the examples for different use cases.

This library is meant to assist in interfacing with your hardware, either through a uint8_t buffer, or a Stream, such as a Serial interface object.

Class output is enabled by defining a buffer, the class methods format the buffer into useful human readable information. ih::Input (the input parser) will function as normal without an output buffer.

Command length has no restrictions, any printable char or control char that is not your end of line character, token delimiter, or c-string delimiter is a valid commandString. You can have up to config.h:IH_MAX_ARGS_PER_COMMAND number of arguments. At runtime, ih::Input:addCommand() scans ih::Parameters and determines the maximum number of arguments you intend to use, it then allocates a dynamically sized array of flags (bit flags in a future feature) which lives for the duration of the process (one allocation per invocation of ih::Input::begin())

User-defined commands have a general tree structure, each command has its own ih::Parameters struct which is stored in non-volatile program memory (PROGMEM on Arduino platforms).

Individual commands that do not contain a wildcard character (each call to ih::Command) use 8 bytes of RAM (on avr). Commands that contain wildcards use more, how much they use depends on the placement of the wildcard characters, and the command length.

The ih::Command ih::Parameters target function will not execute if the input does not match the ih::Command ih::Parameters ih::Parameters::command, if any arguments are type-invalid, or if an unexpected amount of arguments are received.

To make input matching more performant, ih::Parameters::command that contain one or more ih::WildcardChar have their memcmp ranges computed at runtime for each command containing a wildcard char, each memcmp range that needs to be remembered uses ((1 + (1 + 1*n_wcc_containing_prm) + 1) + n_memcmp_ranges*2) bytes. ****, 8***, *8**, **8*, ***8 would compute one memcmp range 8**8 computes as two, 8888 doesn’t have any wcc, so it would undergo “length of input” memcmp. Memcmp ranges are command-wide, if you have a nested command it will only have one associated ih::CommandRuntimeCalc struct.

InputHandler uses C++11 Aggregate initialization for ih::Parameters and ih::InputParameters structs.

Class output is enabled by defining a buffer, the class methods format the buffer into useful human readable information.

Default InputHandler Input constructor initialization with no output:

/*
  InputHandler default Input constructor uses InputParameters variables defined in the namespace ihc src/config/utility/namespace.h
*/
#include <InputHandler.h>
using namespace ih;

Input inputHandler;

Default InputHandler Input constructor initialization with output buffer:

/*
  InputHandler default Input constructor uses InputParameters variables defined in the namespace ihc src/config/utility/namespace.h
  This constructor will output messages into `output_buffer`, you can check to see if there's a message with ih::Input::isOutputAvailable()
*/
#include <InputHandler.h>
using namespace ih;
char output_buffer[512] = {'\0'}; //  output buffer
Input inputHandler(output_buffer, buffsz(output_buffer)); // Input constructor with output buffer and buffer length

Many aspects of InputParameters are customizable:

#include <InputHandler.h>
using namespace ih;

// char array typdef aliases
const PROGMEM ProcessName process_name = "_test_"; // process name
const PROGMEM EndOfLineChar process_eol = "\r\n";  // end of line characters
const PROGMEM ControlCharSeq process_ccseq = "##"; // input control character sequence
const PROGMEM WildcardChar process_wcc = "*";      // process wildcard character

// ih_auto::size_t, {ih_auto::size_t,...}, {ih_auto::char_array,...}
const PROGMEM DelimiterSequences process_delimseq = {
  1,    // number of delimiter sequences
  {1},  // delimiter sequence lens
  {" "} // delimiter sequences
};

// ih_auto::size_t, {ih_auto::size_t,...}, {ih_auto::char_array,...}
const PROGMEM StartStopSequences process_ststpseq = {
  1,           // num start stop sequence pairs
  {1, 1},      // start stop sequence lens
  {"\"", "\""} // start stop sequence pairs
};

const PROGMEM InputParameters input_prm[1] = {
  &process_name,
  &process_eol,
  &process_ccseq,
  &process_wcc,
  &process_delimseq,
  &process_ststpseq
};

char output_buffer[512] = {'\0'}; //  output buffer
Input inputHandler(input_prm, output_buffer, buffsz(output_buffer)); // Input constructor

A valid command string would look like this with the above InputParameters:

your_command arg_1 arg_2 arg... "arguments enclosed with start/stop delimiter sequences can have any char value 0-255, you can memcpy these argument types directly into a recipient struct (size - 1 to remove the null terminator) as uint8_t"
your_command subcommand_1 subcommand_2 ... subcommand_N subcommand_N_arg1 subcommand_N_arg2 ...
y*ur_co***** ...

ih::Input’s input methods are:

void getCommandFromStream(Stream &stream, size_t rx_buffer_size = IH_MAX_PROC_INPUT_LEN);

Or, if you don’t want to use a Stream object use this method instead:

void readCommandFromBuffer(uint8_t *data, size_t len);

This method will output to any initialized stream (hardware or software Serial):

void ih::Input::outputToStream(Stream &stream);

or, you can check to see if ihout output is available with:

bool ih::Input::outputIsAvailable();

and then when you are done with the output buffer, it needs to be reinitialized with:

void ih::Input::clearOutputBuffer();

Bug Reporting#

Please report any bugs in InputHandler/src/ using bug_report.md at InputHandler/src/ bug report forum

Library Build Status#

https://github.com/dstroy0/InputHandler/actions/workflows/adafruit_platforms.yml/badge.svg:target:https://github.com/dstroy0/InputHandler/actions/workflows/adafruit_platforms.yml:alt:Adafruitplatforms:raw-html-md:`<br/>` https://github.com/dstroy0/InputHandler/actions/workflows/arduino_platforms.yml/badge.svg:target:https://github.com/dstroy0/InputHandler/actions/workflows/arduino_platforms.yml:alt:Arduinoplatforms:raw-html-md:`<br/>` https://github.com/dstroy0/InputHandler/actions/workflows/esp32_platforms.yml/badge.svg:target:https://github.com/dstroy0/InputHandler/actions/workflows/esp32_platforms.yml:alt:ESP32platforms:raw-html-md:`<br/>` https://github.com/dstroy0/InputHandler/actions/workflows/esp8266_platforms.yml/badge.svg:target:https://github.com/dstroy0/InputHandler/actions/workflows/esp8266_platforms.yml:alt:ESP8266platforms:raw-html-md:`<br/>` https://github.com/dstroy0/InputHandler/actions/workflows/rpi_platforms.yml/badge.svg:target:https://github.com/dstroy0/InputHandler/actions/workflows/rpi_platforms.yml:alt:RPiplatforms:raw-html-md:`<br/>` Teensyduino platforms

Docs Build Status#

Docs CI

Source Format Conformity#

src-cpp-linter CI

Prebuilt cli_gen_tool Binaries#

Made with PyInstaller

Download for linux build linux binary Download for macos build macos binary Download for windows build windows binary

Design Goals#

Ease of use.
Implementation and platform flexibility.
Feature rich.
Low memory use.
Parse uint8_t, any value 0-255 char array.
Inter equipment interfacing.
Construct complex commands with subcommands, and enforce the input type.
Nested commands with no wildcards use 8 bytes or less of sram (avr).

News#

See the releases’ descriptions on the library’s release page for a list of changes.

Supported Platforms#

Not supported:
ATTiny85 – memory/flash
ATMegaNG – flash
adafruit:samd:adafruit_neotrinkey_m0 – doesn’t build
adafruit:samd:adafruit_pybadge_airlift_m4 – doesn’t build
arduino:samd:nano_33_iot – doesn’t build

If your board is not listed as not supported open an issue if you’d like it added to build coverage.

NOTE: vsnprintf and dtostrf implemented on the following platforms:
(see: src/config/noedit.h for your platform’s implementation)
SAMD,
MBED,
arduino DUE

Build coverage:
Arduino
platformIO

InputHandler library documentation note#

The docs use a feature not supported by every browser to jump to C++ source text. Source links will still take you to the source file, but to take advantage of url-scroll-to-text-fragment you need to use a supported browser, like chrome. Alternatively you can install an addon into firefox auto find text fragment to enable the functionality.