diff --git a/include/CommandManager.h b/include/CommandManager.h index c6053b4..bdbdc5d 100644 --- a/include/CommandManager.h +++ b/include/CommandManager.h @@ -6,6 +6,90 @@ #include #include +#if defined(__EXCEPTIONS) + +#include + +class CommandIDOutOfRangeException : public std::exception +{ +public: + const int mid; + CommandIDOutOfRangeException(int id) : mid(id) + { + } + const char* what() const throw() + { + auto res = std::string("Id out of range "); + int id = mid; + res += std::to_string(id); + return res.c_str(); + } +}; + +class ParamSizeMismatchException : public std::exception +{ +public: + int expectedSize; + int actualSize; + ParamSizeMismatchException(int expectedSize, int actualSize) + { + this->expectedSize = expectedSize; + this->actualSize = actualSize; + } + + const char* what() const throw() + { + const auto res = std::string("Parameter size mismatch, expected ") + + std::to_string(this->expectedSize) + + " but got " + + std::to_string(this->actualSize); + return res.c_str(); + } +}; + +class CallbackNullException : public std::exception +{ +public: + CallbackNullException() {} + const char* what() const throw() + { + return "Callback is not assigned. You forgot to set the callback: CommandManager.setSendCB(&sendCallback)"; + } +}; + +class PeekIDException : public std::exception +{ +public: + PeekIDException(){} + const char* what() const throw() + { + return "Failed to peek ID"; + } +}; + +class ReadIDException : public std::exception +{ +public: + ReadIDException(){} + const char* what() const throw() + { + return "Failed to read ID"; + } +}; + +class ReadParamException : public std::exception +{ +public: + ReadParamException(){} + const char* what() const throw() + { + return "Failed to read param"; + } +}; + +#endif // __EXCEPTIONS + + class _CommandManager { public: @@ -35,14 +119,56 @@ class _CommandManager _CommandManager(size_t inBufferLength, size_t outBufferLength); + /** + * @brief The status of the command manager + * + * @return A StatusCode + */ StatusCode status(); + + /** + * @brief Handle a command + * + * @param buffer A raw byte array + * @param length The number of bytes to use from the buffer + * @return true If successful + * @return false If failed + * @throws CommandIDOutOfRangeException If the command ID is out of range + * @throws ParamSizeMismatchException If the parameter size is different than expected + * @throws CallbackNullException If the command manager send callback hasn't been set + */ bool handleCommand(const uint8_t *buffer, size_t length); + /** + * @brief Handle a command + * + * @param buffer A raw byte array + * @param length The number of bytes to use from the buffer + * @return true If successful + * @return false If failed + * @throws CommandIDOutOfRangeException If the command ID is out of range + * @throws ParamSizeMismatchException If the parameter size is different than expected + * @throws CallbackNullException If the command manager send callback hasn't been set + * @throws PeekIDException If peeking the id from the buffer fails + * @throws ReadIDException If reading the id from the buffer fails + * @throws ReadParamException If reading the parameters from the buffer fails + */ bool handleCommand(Buffer& buff); + /** + * @brief Set the Send callback function + * + * @param cb A function pointer with the signature void (*)(uint8_t*, size_t) + */ void setSendCB(sendCB_t cb); + /** + * @brief Set the command array + * + * @param commands Commands array as given in api.h, generated by the capra_micro_comm_py package + * @param length The number of commands (COMMANDS_COUNT) + */ void setCommands(BaseFunction_ptr* commands, size_t length); ~_CommandManager(); diff --git a/include/common.h b/include/common.h index f4e4f6a..8417e06 100644 --- a/include/common.h +++ b/include/common.h @@ -34,8 +34,8 @@ class EmptyStream : public Stream }; #ifndef SAM - extern EmptyStream debug; - extern HardwareSerial& comm; + extern EmptyStream debug = EmptyStream(); + extern Serial_& comm = Serial #else extern Serial_& debug; extern UARTClass& comm; @@ -90,12 +90,23 @@ using eboolean_t = bool; #define debugBytes(b, c) #include -#include "algorithm" +#include #define GMin(x, y) (std::min(x,y)) #endif // ARDUINO +#if defined(__EXCEPTIONS) +#include +#include +#define THROW_EXCEPTION(exc) throw exc + +#else + +// Define empty if not supported +#define THROW_EXCEPTION(exc) + +#endif // __EXCEPTIONS // Verify type lengths static_assert(sizeof(uint8_t) == 1); diff --git a/library.json b/library.json index 59ee6f1..8ce9015 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "capra_micro_comm", - "version": "1.1.1", + "version": "1.2.0", "description": "This is a very basic implementation of a Remote Procedure Call (RPC) designed to be platform independant and interface independant.", "keywords": "rpc, capra, communication, remote", "repository": @@ -22,4 +22,4 @@ }, "frameworks": "*", "platforms": "*" -} \ No newline at end of file +} diff --git a/platformio.ini b/platformio.ini index 6bb7c68..0c6f867 100644 --- a/platformio.ini +++ b/platformio.ini @@ -14,7 +14,6 @@ test_framework = unity platform = atmelavr board = uno lib_deps = densaugeo/base64@^1.4.0 -test_build_src = yes [env:due] framework = arduino diff --git a/src/CommandManager.cpp b/src/CommandManager.cpp index 893c0a6..7f5b7f6 100644 --- a/src/CommandManager.cpp +++ b/src/CommandManager.cpp @@ -23,6 +23,7 @@ bool _CommandManager::handleCommand(const uint8_t *buffer, size_t length) if (cmdID >= mCommandsCount) { mStatusCode = StatusCode::CMD_ID_OUT_OF_RANGE; + THROW_EXCEPTION(CommandIDOutOfRangeException(cmdID)); return false; } @@ -30,6 +31,7 @@ bool _CommandManager::handleCommand(const uint8_t *buffer, size_t length) if (mCommands[cmdID]->paramSize() > length-1) { mStatusCode = StatusCode::PARAM_SIZE_MISMATCH; + THROW_EXCEPTION(ParamSizeMismatchException(mCommands[cmdID]->paramSize(), length-1)); return false; } @@ -51,6 +53,7 @@ bool _CommandManager::handleCommand(const uint8_t *buffer, size_t length) if (mSendCB == nullptr) { mStatusCode = StatusCode::CALLBACK_NULL; + THROW_EXCEPTION(CallbackNullException()); return false; } mSendCB(output.buffer, output.length); @@ -85,6 +88,7 @@ bool _CommandManager::handleCommand(Buffer& buff) if (cmdID == -1) { mStatusCode = StatusCode::PEEK_ID_ERROR; + THROW_EXCEPTION(PeekIDException()); return false; } @@ -92,6 +96,7 @@ bool _CommandManager::handleCommand(Buffer& buff) if (cmdID >= (int)mCommandsCount) { mStatusCode = StatusCode::CMD_ID_OUT_OF_RANGE; + THROW_EXCEPTION(CommandIDOutOfRangeException(cmdID)); return false; } BaseFunction* func = mCommands[cmdID]; @@ -99,9 +104,10 @@ bool _CommandManager::handleCommand(Buffer& buff) DebugVarln(func->returnSize()); // Verify length - if (func->paramSize() + 1 > buff.available()) + if (func->paramSize() > buff.available() - 1) { mStatusCode = StatusCode::PARAM_SIZE_MISMATCH; + THROW_EXCEPTION(ParamSizeMismatchException(func->paramSize(), buff.available() - 1)); return false; } @@ -110,6 +116,7 @@ bool _CommandManager::handleCommand(Buffer& buff) if (r == -1) { mStatusCode = StatusCode::READ_ID_ERROR; + THROW_EXCEPTION(ReadIDException()); return false; } DebugVarln(r); @@ -120,6 +127,7 @@ bool _CommandManager::handleCommand(Buffer& buff) if (rr != func->paramSize()) { mStatusCode = StatusCode::READ_PARAM_ERROR; + THROW_EXCEPTION(ReadParamException()); return false; } @@ -137,6 +145,7 @@ bool _CommandManager::handleCommand(Buffer& buff) if (mSendCB == nullptr) { mStatusCode = StatusCode::CALLBACK_NULL; + THROW_EXCEPTION(CallbackNullException()); return false; } diff --git a/test/test_decode.cpp b/test/test_decode.cpp index 6236ba3..9473d16 100644 --- a/test/test_decode.cpp +++ b/test/test_decode.cpp @@ -6,14 +6,8 @@ uint8_t* inputBuffer = new uint8_t[TEST_BUFFER_SIZE]; uint8_t* outputBuffer = new uint8_t[TEST_BUFFER_SIZE]; _CommandManager* cmdMan = &CommandManager; - -#ifndef SAM - EmptyStream debug = EmptyStream(); - HardwareSerial& comm = Serial; -#else - Serial_& debug = SerialUSB; - UARTClass& comm = Serial; -#endif +// _CommandManager* cmdMan; +Serial_& debug = SerialUSB; void setUp() {