diff --git a/core/include/librmcs/data/datas.hpp b/core/include/librmcs/data/datas.hpp index 0a3de49..04d5b43 100644 --- a/core/include/librmcs/data/datas.hpp +++ b/core/include/librmcs/data/datas.hpp @@ -112,6 +112,21 @@ struct TemperatureDataView { uint32_t timestamp_quarter_us; }; +/** + * @brief Interface for consuming deserialized uplink data. + * + * This interface is invoked after the protocol layer has already identified the payload type and + * decoded its contents. For callback families that are further multiplexed by a sub-identifier, + * such as `DataId` or a GPIO `channel_index`, the callback returns `bool` to report whether that + * sub-identifier is valid for the concrete implementation. + * + * Return `true` when the sub-identifier is recognized and the payload has been dispatched. + * Return `false` when deserialization succeeded but the `DataId` or `channel_index` is unexpected, + * so the caller can propagate that routing error to upper layers. + * + * IMU callbacks return `void` because each payload type maps to a single callback and requires no + * additional route validation. + */ class DataCallback { public: DataCallback() = default; @@ -121,21 +136,17 @@ class DataCallback { DataCallback& operator=(DataCallback&&) = delete; virtual ~DataCallback() = default; - // `*_receive_callback` returns `true` if id is valid - virtual bool can_receive_callback(DataId id, const CanDataView& data) = 0; + [[nodiscard]] virtual bool can_receive_callback(DataId id, const CanDataView& data) = 0; - virtual bool uart_receive_callback(DataId id, const UartDataView& data) = 0; + [[nodiscard]] virtual bool uart_receive_callback(DataId id, const UartDataView& data) = 0; - virtual void gpio_digital_read_result_callback( + [[nodiscard]] virtual bool gpio_digital_read_result_callback( uint8_t channel_index, const GpioDigitalDataView& data) = 0; - - virtual void + [[nodiscard]] virtual bool gpio_analog_read_result_callback(uint8_t channel_index, const GpioAnalogDataView& data) = 0; virtual void accelerometer_receive_callback(const AccelerometerDataView& data) = 0; - virtual void gyroscope_receive_callback(const GyroscopeDataView& data) = 0; - virtual void temperature_receive_callback(const TemperatureDataView& data) = 0; }; diff --git a/host/include/librmcs/agent/c_board.hpp b/host/include/librmcs/agent/c_board.hpp index 0611622..382ed6c 100644 --- a/host/include/librmcs/agent/c_board.hpp +++ b/host/include/librmcs/agent/c_board.hpp @@ -12,16 +12,105 @@ namespace librmcs::agent { -class CBoard : private data::DataCallback { +/** + * @brief High-level host agent for C Board. + * + * This class owns the transport and protocol stack for a single board connection. + * The supplied `Callback` is stored by reference, is not owned by the board, and must outlive the + * board instance. + * + * The board may start transport I/O during construction, so receive callbacks may be invoked before + * the board constructor returns. + * + * A common usage pattern is for an enclosing user type to inherit `Callback` and declare the board + * as its last data member. In that arrangement, early callbacks may access base subobjects and + * members whose initialization has already completed before the board member begins construction. + * + * @warning Early callbacks must not depend on invariants established later in an enclosing + * constructor body, on post-construction configuration, or on the board object itself having + * finished construction. Delay board construction with `std::optional` or `std::unique_ptr` when + * callback behavior depends on such state. + */ +class CBoard final { public: - explicit CBoard(std::string_view serial_filter = {}, const AdvancedOptions& options = {}) - : handler_(0xA11C, 0xD401, serial_filter, options, *this) {} + class Callback : public data::DataCallback { + public: + virtual void can1_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } + virtual void can2_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } + + virtual void dbus_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } + virtual void uart1_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } + virtual void uart2_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } + + virtual void gpio_digital_read_result_callback( + const librmcs::spec::c_board::GpioDescriptor& gpio, + const librmcs::data::GpioDigitalDataView& data) { + (void)gpio; + (void)data; + } + virtual void gpio_analog_read_result_callback( + const librmcs::spec::c_board::GpioDescriptor& gpio, + const librmcs::data::GpioAnalogDataView& data) { + (void)gpio; + (void)data; + } + + void accelerometer_receive_callback( + const librmcs::data::AccelerometerDataView& data) override { + (void)data; + } + void gyroscope_receive_callback(const librmcs::data::GyroscopeDataView& data) override { + (void)data; + } + void temperature_receive_callback(const librmcs::data::TemperatureDataView& data) override { + (void)data; + } + + public: + bool can_receive_callback(data::DataId id, const data::CanDataView& data) final { + switch (id) { + case data::DataId::kCan1: can1_receive_callback(data); return true; + case data::DataId::kCan2: can2_receive_callback(data); return true; + default: return false; + } + } + + bool uart_receive_callback(data::DataId id, const data::UartDataView& data) final { + switch (id) { + case data::DataId::kUartDbus: dbus_receive_callback(data); return true; + case data::DataId::kUart1: uart1_receive_callback(data); return true; + case data::DataId::kUart2: uart2_receive_callback(data); return true; + default: return false; + } + } + + bool gpio_digital_read_result_callback( + uint8_t channel_index, const data::GpioDigitalDataView& data) final { + if (channel_index >= spec::c_board::kGpioDescriptors.size()) [[unlikely]] + return false; + gpio_digital_read_result_callback(spec::c_board::kGpioDescriptors[channel_index], data); + return true; + } + + bool gpio_analog_read_result_callback( + uint8_t channel_index, const data::GpioAnalogDataView& data) final { + if (channel_index >= spec::c_board::kGpioDescriptors.size()) [[unlikely]] + return false; + gpio_analog_read_result_callback(spec::c_board::kGpioDescriptors[channel_index], data); + return true; + } + }; + + explicit CBoard( + Callback& callback = default_callback_, std::string_view serial_filter = {}, + const AdvancedOptions& options = {}) + : handler_(0xA11C, 0xD401, serial_filter, options, callback) {} CBoard(const CBoard&) = delete; CBoard& operator=(const CBoard&) = delete; CBoard(CBoard&&) = delete; CBoard& operator=(CBoard&&) = delete; - ~CBoard() override = default; + ~CBoard() = default; class PacketBuilder { friend class CBoard; @@ -84,66 +173,7 @@ class CBoard : private data::DataCallback { PacketBuilder start_transmit() noexcept { return PacketBuilder{handler_}; } private: - bool can_receive_callback(data::DataId id, const data::CanDataView& data) final { - switch (id) { - case data::DataId::kCan1: can1_receive_callback(data); return true; - case data::DataId::kCan2: can2_receive_callback(data); return true; - default: return false; - } - } - - virtual void can1_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } - virtual void can2_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } - - bool uart_receive_callback(data::DataId id, const data::UartDataView& data) final { - switch (id) { - case data::DataId::kUartDbus: dbus_receive_callback(data); return true; - case data::DataId::kUart1: uart1_receive_callback(data); return true; - case data::DataId::kUart2: uart2_receive_callback(data); return true; - default: return false; - } - } - - virtual void dbus_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } - virtual void uart1_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } - virtual void uart2_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } - - virtual void gpio_digital_read_result_callback( - const librmcs::spec::c_board::GpioDescriptor& gpio, - const librmcs::data::GpioDigitalDataView& data) { - (void)gpio; - (void)data; - } - virtual void gpio_analog_read_result_callback( - const librmcs::spec::c_board::GpioDescriptor& gpio, - const librmcs::data::GpioAnalogDataView& data) { - (void)gpio; - (void)data; - } - - void gpio_digital_read_result_callback( - uint8_t channel_index, const librmcs::data::GpioDigitalDataView& data) override { - if (channel_index >= spec::c_board::kGpioDescriptors.size()) [[unlikely]] - return; - gpio_digital_read_result_callback(spec::c_board::kGpioDescriptors[channel_index], data); - } - void gpio_analog_read_result_callback( - uint8_t channel_index, const librmcs::data::GpioAnalogDataView& data) override { - if (channel_index >= spec::c_board::kGpioDescriptors.size()) [[unlikely]] - return; - gpio_analog_read_result_callback(spec::c_board::kGpioDescriptors[channel_index], data); - } - - void accelerometer_receive_callback(const librmcs::data::AccelerometerDataView& data) override { - (void)data; - } - void gyroscope_receive_callback(const librmcs::data::GyroscopeDataView& data) override { - (void)data; - } - void temperature_receive_callback(const librmcs::data::TemperatureDataView& data) override { - (void)data; - } - + static inline Callback default_callback_{}; host::protocol::Handler handler_; }; diff --git a/host/include/librmcs/agent/common.hpp b/host/include/librmcs/agent/common.hpp index f8ffb3f..69c039c 100644 --- a/host/include/librmcs/agent/common.hpp +++ b/host/include/librmcs/agent/common.hpp @@ -40,11 +40,12 @@ class AdvancedOptions { * This hook is intended only for per-thread environment setup, such as thread priority, * CPU affinity, thread naming, or other OS-level thread configuration. * - * @warning This callback runs during transport construction, before `Handler` and the - * enclosing agent object finish construction. - * @warning The callback must not access the agent object being constructed, any of its - * members, or any transport/protocol APIs. In particular, do not capture and use `this` - * from the constructing agent object. + * @warning This callback runs during transport construction, before the enclosing board object + * finishes construction. If that board is itself a member of another object, that enclosing + * object may also still be under construction. + * @warning The callback must not access the board object being constructed, any state whose + * lifetime depends on construction having finished, or any transport/protocol APIs. In + * particular, do not capture and use `this` from an object that is still being constructed. */ void (*thread_setup)(const AdvancedOptions&) noexcept = nullptr; diff --git a/host/include/librmcs/agent/rmcs_board_lite.hpp b/host/include/librmcs/agent/rmcs_board_lite.hpp index 8b1ad20..0c23538 100644 --- a/host/include/librmcs/agent/rmcs_board_lite.hpp +++ b/host/include/librmcs/agent/rmcs_board_lite.hpp @@ -12,16 +12,111 @@ namespace librmcs::agent { -class RmcsBoardLite : private data::DataCallback { +/** + * @brief High-level host agent for RMCS Board Lite. + * + * This class owns the transport and protocol stack for a single board connection. + * The supplied `Callback` is stored by reference, is not owned by the board, and must outlive the + * board instance. + * + * The board may start transport I/O during construction, so receive callbacks may be invoked before + * the board constructor returns. + * + * A common usage pattern is for an enclosing user type to inherit `Callback` and declare the board + * as its last data member. In that arrangement, early callbacks may access base subobjects and + * members whose initialization has already completed before the board member begins construction. + * + * @warning Early callbacks must not depend on invariants established later in an enclosing + * constructor body, on post-construction configuration, or on the board object itself having + * finished construction. Delay board construction with `std::optional` or `std::unique_ptr` when + * callback behavior depends on such state. + */ +class RmcsBoardLite final { public: - explicit RmcsBoardLite(std::string_view serial_filter = {}, const AdvancedOptions& options = {}) - : handler_(0xA11C, 0xA801, serial_filter, options, *this) {} + class Callback : public data::DataCallback { + public: + virtual void can0_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } + virtual void can1_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } + virtual void can2_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } + virtual void can3_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } + + virtual void dbus_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } + virtual void uart0_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } + virtual void uart1_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } + + virtual void gpio_digital_read_result_callback( + const librmcs::spec::rmcs_board_lite::GpioDescriptor& gpio, + const librmcs::data::GpioDigitalDataView& data) { + (void)gpio; + (void)data; + } + virtual void gpio_analog_read_result_callback( + const librmcs::spec::rmcs_board_lite::GpioDescriptor& gpio, + const librmcs::data::GpioAnalogDataView& data) { + (void)gpio; + (void)data; + } + + void accelerometer_receive_callback( + const librmcs::data::AccelerometerDataView& data) override { + (void)data; + } + void gyroscope_receive_callback(const librmcs::data::GyroscopeDataView& data) override { + (void)data; + } + void temperature_receive_callback(const librmcs::data::TemperatureDataView& data) override { + (void)data; + } + + public: + bool can_receive_callback(data::DataId id, const data::CanDataView& data) final { + switch (id) { + case data::DataId::kCan0: can0_receive_callback(data); return true; + case data::DataId::kCan1: can1_receive_callback(data); return true; + case data::DataId::kCan2: can2_receive_callback(data); return true; + case data::DataId::kCan3: can3_receive_callback(data); return true; + default: return false; + } + } + + bool uart_receive_callback(data::DataId id, const data::UartDataView& data) final { + switch (id) { + case data::DataId::kUartDbus: dbus_receive_callback(data); return true; + case data::DataId::kUart0: uart0_receive_callback(data); return true; + case data::DataId::kUart1: uart1_receive_callback(data); return true; + default: return false; + } + } + + bool gpio_digital_read_result_callback( + uint8_t channel_index, const data::GpioDigitalDataView& data) final { + if (channel_index >= spec::rmcs_board_lite::kGpioDescriptors.size()) [[unlikely]] + return false; + gpio_digital_read_result_callback( + spec::rmcs_board_lite::kGpioDescriptors[channel_index], data); + return true; + } + + bool gpio_analog_read_result_callback( + uint8_t channel_index, const data::GpioAnalogDataView& data) final { + if (channel_index >= spec::rmcs_board_lite::kGpioDescriptors.size()) [[unlikely]] + return false; + gpio_analog_read_result_callback( + spec::rmcs_board_lite::kGpioDescriptors[channel_index], data); + return true; + } + }; + + explicit RmcsBoardLite( + Callback& callback = default_callback_, std::string_view serial_filter = {}, + const AdvancedOptions& options = {}) + : handler_(0xA11C, 0xA801, serial_filter, options, callback) {} RmcsBoardLite(const RmcsBoardLite&) = delete; RmcsBoardLite& operator=(const RmcsBoardLite&) = delete; RmcsBoardLite(RmcsBoardLite&&) = delete; RmcsBoardLite& operator=(RmcsBoardLite&&) = delete; - ~RmcsBoardLite() override = default; + ~RmcsBoardLite() = default; class PacketBuilder { friend class RmcsBoardLite; @@ -94,72 +189,7 @@ class RmcsBoardLite : private data::DataCallback { PacketBuilder start_transmit() noexcept { return PacketBuilder{handler_}; } private: - bool can_receive_callback(data::DataId id, const data::CanDataView& data) final { - switch (id) { - case data::DataId::kCan0: can0_receive_callback(data); return true; - case data::DataId::kCan1: can1_receive_callback(data); return true; - case data::DataId::kCan2: can2_receive_callback(data); return true; - case data::DataId::kCan3: can3_receive_callback(data); return true; - default: return false; - } - } - - virtual void can0_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } - virtual void can1_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } - virtual void can2_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } - virtual void can3_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } - - bool uart_receive_callback(data::DataId id, const data::UartDataView& data) final { - switch (id) { - case data::DataId::kUartDbus: dbus_receive_callback(data); return true; - case data::DataId::kUart0: uart0_receive_callback(data); return true; - case data::DataId::kUart1: uart1_receive_callback(data); return true; - default: return false; - } - } - - virtual void dbus_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } - virtual void uart0_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } - virtual void uart1_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } - - virtual void gpio_digital_read_result_callback( - const librmcs::spec::rmcs_board_lite::GpioDescriptor& gpio, - const librmcs::data::GpioDigitalDataView& data) { - (void)gpio; - (void)data; - } - virtual void gpio_analog_read_result_callback( - const librmcs::spec::rmcs_board_lite::GpioDescriptor& gpio, - const librmcs::data::GpioAnalogDataView& data) { - (void)gpio; - (void)data; - } - - void gpio_digital_read_result_callback( - uint8_t channel_index, const librmcs::data::GpioDigitalDataView& data) final { - if (channel_index >= spec::rmcs_board_lite::kGpioDescriptors.size()) [[unlikely]] - return; - gpio_digital_read_result_callback( - spec::rmcs_board_lite::kGpioDescriptors[channel_index], data); - } - void gpio_analog_read_result_callback( - uint8_t channel_index, const librmcs::data::GpioAnalogDataView& data) final { - if (channel_index >= spec::rmcs_board_lite::kGpioDescriptors.size()) [[unlikely]] - return; - gpio_analog_read_result_callback( - spec::rmcs_board_lite::kGpioDescriptors[channel_index], data); - } - - void accelerometer_receive_callback(const librmcs::data::AccelerometerDataView& data) override { - (void)data; - } - void gyroscope_receive_callback(const librmcs::data::GyroscopeDataView& data) override { - (void)data; - } - void temperature_receive_callback(const librmcs::data::TemperatureDataView& data) override { - (void)data; - } - + static inline Callback default_callback_{}; host::protocol::Handler handler_; }; diff --git a/host/include/librmcs/agent/rmcs_board_pro.hpp b/host/include/librmcs/agent/rmcs_board_pro.hpp index 2920af9..3e7523f 100644 --- a/host/include/librmcs/agent/rmcs_board_pro.hpp +++ b/host/include/librmcs/agent/rmcs_board_pro.hpp @@ -12,16 +12,115 @@ namespace librmcs::agent { -class RmcsBoardPro : private data::DataCallback { +/** + * @brief High-level host agent for RMCS Board Pro. + * + * This class owns the transport and protocol stack for a single board connection. + * The supplied `Callback` is stored by reference, is not owned by the board, and must outlive the + * board instance. + * + * The board may start transport I/O during construction, so receive callbacks may be invoked before + * the board constructor returns. + * + * A common usage pattern is for an enclosing user type to inherit `Callback` and declare the board + * as its last data member. In that arrangement, early callbacks may access base subobjects and + * members whose initialization has already completed before the board member begins construction. + * + * @warning Early callbacks must not depend on invariants established later in an enclosing + * constructor body, on post-construction configuration, or on the board object itself having + * finished construction. Delay board construction with `std::optional` or `std::unique_ptr` when + * callback behavior depends on such state. + */ +class RmcsBoardPro final { public: - explicit RmcsBoardPro(std::string_view serial_filter = {}, const AdvancedOptions& options = {}) - : handler_(0xA11C, 0xAF01, serial_filter, options, *this) {} + class Callback : public data::DataCallback { + public: + virtual void can0_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } + virtual void can1_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } + virtual void can2_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } + virtual void can3_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } + + virtual void dbus_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } + virtual void uart0_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } + virtual void uart1_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } + virtual void uart2_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } + virtual void uart3_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } + + virtual void gpio_digital_read_result_callback( + const librmcs::spec::rmcs_board_pro::GpioDescriptor& gpio, + const librmcs::data::GpioDigitalDataView& data) { + (void)gpio; + (void)data; + } + virtual void gpio_analog_read_result_callback( + const librmcs::spec::rmcs_board_pro::GpioDescriptor& gpio, + const librmcs::data::GpioAnalogDataView& data) { + (void)gpio; + (void)data; + } + + void accelerometer_receive_callback( + const librmcs::data::AccelerometerDataView& data) override { + (void)data; + } + void gyroscope_receive_callback(const librmcs::data::GyroscopeDataView& data) override { + (void)data; + } + void temperature_receive_callback(const librmcs::data::TemperatureDataView& data) override { + (void)data; + } + + public: + bool can_receive_callback(data::DataId id, const data::CanDataView& data) final { + switch (id) { + case data::DataId::kCan0: can0_receive_callback(data); return true; + case data::DataId::kCan1: can1_receive_callback(data); return true; + case data::DataId::kCan2: can2_receive_callback(data); return true; + case data::DataId::kCan3: can3_receive_callback(data); return true; + default: return false; + } + } + + bool uart_receive_callback(data::DataId id, const data::UartDataView& data) final { + switch (id) { + case data::DataId::kUartDbus: dbus_receive_callback(data); return true; + case data::DataId::kUart0: uart0_receive_callback(data); return true; + case data::DataId::kUart1: uart1_receive_callback(data); return true; + case data::DataId::kUart2: uart2_receive_callback(data); return true; + case data::DataId::kUart3: uart3_receive_callback(data); return true; + default: return false; + } + } + + bool gpio_digital_read_result_callback( + uint8_t channel_index, const data::GpioDigitalDataView& data) final { + if (channel_index >= spec::rmcs_board_pro::kGpioDescriptors.size()) [[unlikely]] + return false; + gpio_digital_read_result_callback( + spec::rmcs_board_pro::kGpioDescriptors[channel_index], data); + return true; + } + + bool gpio_analog_read_result_callback( + uint8_t channel_index, const data::GpioAnalogDataView& data) final { + if (channel_index >= spec::rmcs_board_pro::kGpioDescriptors.size()) [[unlikely]] + return false; + gpio_analog_read_result_callback( + spec::rmcs_board_pro::kGpioDescriptors[channel_index], data); + return true; + } + }; + + explicit RmcsBoardPro( + Callback& callback = default_callback_, std::string_view serial_filter = {}, + const AdvancedOptions& options = {}) + : handler_(0xA11C, 0xAF01, serial_filter, options, callback) {} RmcsBoardPro(const RmcsBoardPro&) = delete; RmcsBoardPro& operator=(const RmcsBoardPro&) = delete; RmcsBoardPro(RmcsBoardPro&&) = delete; RmcsBoardPro& operator=(RmcsBoardPro&&) = delete; - ~RmcsBoardPro() override = default; + ~RmcsBoardPro() = default; class PacketBuilder { friend class RmcsBoardPro; @@ -104,76 +203,7 @@ class RmcsBoardPro : private data::DataCallback { PacketBuilder start_transmit() noexcept { return PacketBuilder{handler_}; } private: - bool can_receive_callback(data::DataId id, const data::CanDataView& data) final { - switch (id) { - case data::DataId::kCan0: can0_receive_callback(data); return true; - case data::DataId::kCan1: can1_receive_callback(data); return true; - case data::DataId::kCan2: can2_receive_callback(data); return true; - case data::DataId::kCan3: can3_receive_callback(data); return true; - default: return false; - } - } - - virtual void can0_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } - virtual void can1_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } - virtual void can2_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } - virtual void can3_receive_callback(const librmcs::data::CanDataView& data) { (void)data; } - - bool uart_receive_callback(data::DataId id, const data::UartDataView& data) final { - switch (id) { - case data::DataId::kUartDbus: dbus_receive_callback(data); return true; - case data::DataId::kUart0: uart0_receive_callback(data); return true; - case data::DataId::kUart1: uart1_receive_callback(data); return true; - case data::DataId::kUart2: uart2_receive_callback(data); return true; - case data::DataId::kUart3: uart3_receive_callback(data); return true; - default: return false; - } - } - - virtual void dbus_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } - virtual void uart0_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } - virtual void uart1_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } - virtual void uart2_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } - virtual void uart3_receive_callback(const librmcs::data::UartDataView& data) { (void)data; } - - void gpio_digital_read_result_callback( - uint8_t channel_index, const librmcs::data::GpioDigitalDataView& data) final { - if (channel_index >= spec::rmcs_board_pro::kGpioDescriptors.size()) [[unlikely]] - return; - gpio_digital_read_result_callback( - spec::rmcs_board_pro::kGpioDescriptors[channel_index], data); - } - void gpio_analog_read_result_callback( - uint8_t channel_index, const librmcs::data::GpioAnalogDataView& data) final { - if (channel_index >= spec::rmcs_board_pro::kGpioDescriptors.size()) [[unlikely]] - return; - gpio_analog_read_result_callback( - spec::rmcs_board_pro::kGpioDescriptors[channel_index], data); - } - - virtual void gpio_digital_read_result_callback( - const librmcs::spec::rmcs_board_pro::GpioDescriptor& gpio, - const librmcs::data::GpioDigitalDataView& data) { - (void)gpio; - (void)data; - } - virtual void gpio_analog_read_result_callback( - const librmcs::spec::rmcs_board_pro::GpioDescriptor& gpio, - const librmcs::data::GpioAnalogDataView& data) { - (void)gpio; - (void)data; - } - - void accelerometer_receive_callback(const librmcs::data::AccelerometerDataView& data) override { - (void)data; - } - void gyroscope_receive_callback(const librmcs::data::GyroscopeDataView& data) override { - (void)data; - } - void temperature_receive_callback(const librmcs::data::TemperatureDataView& data) override { - (void)data; - } - + static inline Callback default_callback_{}; host::protocol::Handler handler_; }; diff --git a/host/src/protocol/handler.cpp b/host/src/protocol/handler.cpp index b7bc504..27020de 100644 --- a/host/src/protocol/handler.cpp +++ b/host/src/protocol/handler.cpp @@ -81,14 +81,18 @@ class Handler::Impl : public core::protocol::DeserializeCallback { uint8_t channel_index, const data::GpioDigitalDataView& data) override { if (!session_established()) return; - callback_.gpio_digital_read_result_callback(channel_index, data); + if (!callback_.gpio_digital_read_result_callback(channel_index, data)) + logging::get_logger().error( + "Unexpected gpio channel index: ", static_cast(channel_index)); } void gpio_analog_data_deserialized_callback( uint8_t channel_index, const data::GpioAnalogDataView& data) override { if (!session_established()) return; - callback_.gpio_analog_read_result_callback(channel_index, data); + if (!callback_.gpio_analog_read_result_callback(channel_index, data)) + logging::get_logger().error( + "Unexpected gpio channel index: ", static_cast(channel_index)); } void gpio_digital_read_config_deserialized_callback(