Skip to content

Commit

Permalink
feat(core): add more concrete ways of sending data
Browse files Browse the repository at this point in the history
  • Loading branch information
GwnDaan committed Nov 10, 2023
1 parent 6fb8fd8 commit 32e713b
Show file tree
Hide file tree
Showing 9 changed files with 549 additions and 116 deletions.
4 changes: 2 additions & 2 deletions examples/transport_layer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ int main()
}

// Send a classic CAN message to global (0xFF) (8 bytes or less)
if (running && isobus::CANNetworkManager::CANNetwork.send_can_message(0xEF00, ETPTestBuffer, isobus::CAN_DATA_LENGTH, TestInternalECU))
if (running && isobus::CANNetworkManager::CANNetwork.send_can_message_global(0xEF00, ETPTestBuffer, isobus::CAN_DATA_LENGTH, TestInternalECU))
{
std::cout << "Sent a broadcast CAN Message with length 8" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(4)); // Arbitrary
Expand Down Expand Up @@ -139,7 +139,7 @@ int main()
}

// Send message
if (isobus::CANNetworkManager::CANNetwork.send_can_message(0xEF00, TPTestBuffer, i, TestInternalECU))
if (isobus::CANNetworkManager::CANNetwork.send_can_message_global(0xEF00, TPTestBuffer, i, TestInternalECU))
{
std::cout << "Started BAM Session with length " << i << std::endl;
}
Expand Down
104 changes: 104 additions & 0 deletions isobus/include/isobus/isobus/can_message_data.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//================================================================================================
/// @file can_message_data.hpp
///
/// @brief Contains common types and functions for working with the data of a CAN message.
/// @author Daan Steenbergen
///
/// @copyright 2022 Open Agriculture
//================================================================================================
#ifndef CAN_MESSAGE_DATA_HPP
#define CAN_MESSAGE_DATA_HPP

#include <array>
#include <cstddef>

namespace isobus
{
//================================================================================================
/// @class DataSpan
///
/// @brief A class that represents a span of data of arbitrary length.
//================================================================================================
template<typename T>
class DataSpan
{
public:
/// @brief Construct a new DataSpan object of a writeable array.
/// @param ptr pointer to the buffer to use.
/// @param len The number of elements in the buffer.
DataSpan(T *ptr, std::size_t size) :
ptr(ptr),
_size(size)
{
}

/// @brief Get the element at the given index.
/// @param index The index of the element to get.
/// @return The element at the given index.
T &operator[](std::size_t index)
{
return ptr[index * sizeof(T)];
}

/// @brief Get the element at the given index.
/// @param index The index of the element to get.
/// @return The element at the given index.
T const &operator[](std::size_t index) const
{
return ptr[index * sizeof(T)];
}

/// @brief Get the size of the data span.
/// @return The size of the data span.
std::size_t size() const
{
return _size;
}

/// @brief Get the begin iterator.
/// @return The begin iterator.
T *begin()
{
return ptr;
}

/// @brief Get the end iterator.
/// @return The end iterator.
T *end()
{
return ptr + _size * sizeof(T);
}

private:
T *ptr;
std::size_t _size;
};

//================================================================================================
/// @class DataSpanFactory
///
/// @brief A class that can be used to construct a DataSpan from various types.
//================================================================================================
class DataSpanFactory
{
public:
/// @brief Factory method to create a DataSpan from a std::array.
/// @param array The array to create the DataSpan from.
/// @return The created DataSpan.
template<typename T, std::size_t N>
static DataSpan<T> fromArray(std::array<T, N> &array)
{
return DataSpan<T>(array.data(), N);
}

/// @brief Factory method to create a DataSpan of consts elements from a std::array of non-const elements.
/// @param array The array to create the DataSpan from.
/// @return The created DataSpan of const elements.
template<typename T, std::size_t N>
static DataSpan<std::add_const_t<T>> cfromArray(std::array<T, N> &array)
{
return DataSpan<std::add_const_t<T>>(array.data(), N);
}
};
}
#endif // CAN_MESSAGE_DATA_HPP
159 changes: 146 additions & 13 deletions isobus/include/isobus/isobus/can_network_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "isobus/isobus/can_identifier.hpp"
#include "isobus/isobus/can_internal_control_function.hpp"
#include "isobus/isobus/can_message.hpp"
#include "isobus/isobus/can_message_data.hpp"
#include "isobus/isobus/can_message_frame.hpp"
#include "isobus/isobus/can_network_configuration.hpp"
#include "isobus/isobus/can_transport_protocol.hpp"
Expand Down Expand Up @@ -101,21 +102,156 @@ namespace isobus
/// @returns Estimated busload over the last 1 second
float get_estimated_busload(std::uint8_t canChannel);

/// @brief This is the main way to send a CAN message of any length.
/// @brief Sends a CAN message with the specified parameter group number and data buffer to the specified destination control function.
/// @deprecated Use the `send_can_message` function with a DataSpan instead.
/// @details This function will automatically choose an appropriate transport protocol if needed.
/// If you don't specify a destination (or use nullptr) you message will be sent as a broadcast
/// if it is valid to do so.
/// You can also get a callback on success or failure of the transmit.
/// @returns `true` if the message was sent, otherwise `false`
/// @param parameterGroupNumber The parameter group number of the CAN message.
/// @param dataBuffer The data buffer containing the data to be sent.
/// @param dataLength The length of the data buffer.
/// @param sourceControlFunction The source control function of the CAN message.
/// @param destinationControlFunction The destination control function of the CAN message.
/// @param priority The priority of the CAN message.
/// @param txCompleteCallback The callback function to be called when the transmission is complete.
/// @param parentPointer A pointer to the parent object that gets passed to the txCompleteCallback.
/// @return True if the message is successfully enqueued, false otherwise.
bool send_can_message(std::uint32_t parameterGroupNumber,
const std::uint8_t *dataBuffer,
std::uint32_t dataLength,
std::shared_ptr<InternalControlFunction> sourceControlFunction,
std::shared_ptr<ControlFunction> destinationControlFunction = nullptr,
std::shared_ptr<ControlFunction> destinationControlFunction,
CANIdentifier::CANPriority priority = CANIdentifier::CANPriority::PriorityDefault6,
TransmitCompleteCallback txCompleteCallback = nullptr,
void *parentPointer = nullptr);

/// @brief Sends a CAN message with the specified parameter group number and data from chunk callback
/// to the specified destination control function.
/// @details This function will automatically choose an appropriate transport protocol if needed.
/// If you don't specify a destination (or use nullptr) you message will be sent as a broadcast
/// @param parameterGroupNumber The parameter group number of the CAN message.
/// @param frameChunkCallback The callback function to be called to get the data to be sent in chunks.
/// @param dataLength The total length of the data to be sent.
/// @param sourceControlFunction The source control function of the CAN message.
/// @param destinationControlFunction The destination control function of the CAN message.
/// @param priority The priority of the CAN message.
/// @param txCompleteCallback The callback function to be called when the transmission is complete.
/// @param parentPointer A pointer to the parent object that gets passed to the txCompleteCallback.
/// @return True if the message is successfully enqueued, false otherwise.
bool send_can_message(std::uint32_t parameterGroupNumber,
DataChunkCallback frameChunkCallback,
std::uint32_t dataLength,
std::shared_ptr<InternalControlFunction> sourceControlFunction,
std::shared_ptr<ControlFunction> destinationControlFunction,
CANIdentifier::CANPriority priority = CANIdentifier::CANPriority::PriorityDefault6,
TransmitCompleteCallback txCompleteCallback = nullptr,
void *parentPointer = nullptr);

/// @brief Sends a CAN message with the specified parameter group number and data to the specified destination control function.
/// @details This function will automatically choose an appropriate transport protocol if needed.
/// If you don't specify a destination (or use nullptr) you message will be sent as a broadcast
/// @param parameterGroupNumber The parameter group number of the CAN message.
/// @param data The data to be sent.
/// @param sourceControlFunction The source control function of the CAN message.
/// @param destinationControlFunction The destination control function of the CAN message.
/// @param priority The priority of the CAN message.
/// @param txCompleteCallback The callback function to be called when the transmission is complete.
/// @param parentPointer A pointer to the parent object that gets passed to the txCompleteCallback.
/// @return True if the message is successfully enqueued, false otherwise.
bool send_can_message(std::uint32_t parameterGroupNumber,
DataSpan<const std::uint8_t> data,
std::shared_ptr<InternalControlFunction> sourceControlFunction,
std::shared_ptr<ControlFunction> destinationControlFunction,
CANIdentifier::CANPriority priority = CANIdentifier::CANPriority::PriorityDefault6,
TransmitCompleteCallback txCompleteCallback = nullptr,
void *parentPointer = nullptr);

/// @brief Sends a CAN message with the specified parameter group number and data to the specified destination control function.
/// @details This function will automatically choose an appropriate transport protocol if needed.
/// If you don't specify a destination (or use nullptr) you message will be sent as a broadcast
/// @param parameterGroupNumber The parameter group number of the CAN message.
/// @param data The data to be sent.
/// @param sourceControlFunction The source control function of the CAN message.
/// @param destinationControlFunction The destination control function of the CAN message.
/// @param priority The priority of the CAN message.
/// @param txCompleteCallback The callback function to be called when the transmission is complete.
/// @param parentPointer A pointer to the parent object that gets passed to the txCompleteCallback.
/// @return True if the message is successfully enqueued, false otherwise.
bool send_can_message(std::uint32_t parameterGroupNumber,
std::initializer_list<std::uint8_t> data,
std::shared_ptr<InternalControlFunction> sourceControlFunction,
std::shared_ptr<ControlFunction> destinationControlFunction,
CANIdentifier::CANPriority priority = CANIdentifier::CANPriority::PriorityDefault6,
TransmitCompleteCallback txCompleteCallback = nullptr,
void *parentPointer = nullptr,
DataChunkCallback frameChunkCallback = nullptr);
void *parentPointer = nullptr);

/// @brief Broadcast a CAN message with the specified parameter group number and data buffer. (Destination Address=0xFF)
/// @deprecated Use the `send_can_message_global` function with a DataSpan instead.
/// @details This function will automatically choose an appropriate transport protocol if needed.
/// @param parameterGroupNumber The parameter group number of the CAN message.
/// @param dataBuffer The data buffer containing the data to be sent.
/// @param dataLength The length of the data buffer.
/// @param sourceControlFunction The source control function of the CAN message.
/// @param priority The priority of the CAN message.
/// @param txCompleteCallback The callback function to be called when the transmission is complete.
/// @param parentPointer A pointer to the parent object that gets passed to the txCompleteCallback.
/// @return True if the message is successfully enqueued, false otherwise.
bool send_can_message_global(std::uint32_t parameterGroupNumber,
const std::uint8_t *dataBuffer,
std::uint32_t dataLength,
std::shared_ptr<InternalControlFunction> sourceControlFunction,
CANIdentifier::CANPriority priority = CANIdentifier::CANPriority::PriorityDefault6,
TransmitCompleteCallback txCompleteCallback = nullptr,
void *parentPointer = nullptr);

/// @brief Broadcast a CAN message with the specified parameter group number and data from chunk callback. (Destination Address=0xFF)
/// @details This function will automatically choose an appropriate transport protocol if needed.
/// @param parameterGroupNumber The parameter group number of the CAN message.
/// @param frameChunkCallback The callback function to be called to get the data to be sent in chunks.
/// @param dataLength The total length of the data to be sent.
/// @param sourceControlFunction The source control function of the CAN message.
/// @param priority The priority of the CAN message.
/// @param txCompleteCallback The callback function to be called when the transmission is complete.
/// @param parentPointer A pointer to the parent object that gets passed to the txCompleteCallback.
/// @return True if the message is successfully enqueued, false otherwise.
bool send_can_message_global(std::uint32_t parameterGroupNumber,
DataChunkCallback frameChunkCallback,
std::uint32_t dataLength,
std::shared_ptr<InternalControlFunction> sourceControlFunction,
CANIdentifier::CANPriority priority = CANIdentifier::CANPriority::PriorityDefault6,
TransmitCompleteCallback txCompleteCallback = nullptr,
void *parentPointer = nullptr);

/// @brief Broadcast a CAN message with the specified parameter group number and data. (Destination Address=0xFF)
/// @details This function will automatically choose an appropriate transport protocol if needed.
/// @param parameterGroupNumber The parameter group number of the CAN message.
/// @param data The data to be sent.
/// @param sourceControlFunction The source control function of the CAN message.
/// @param priority The priority of the CAN message.
/// @param txCompleteCallback The callback function to be called when the transmission is complete.
/// @param parentPointer A pointer to the parent object that gets passed to the txCompleteCallback.
/// @return True if the message is successfully enqueued, false otherwise.
bool send_can_message_global(std::uint32_t parameterGroupNumber,
DataSpan<const std::uint8_t> data,
std::shared_ptr<InternalControlFunction> sourceControlFunction,
CANIdentifier::CANPriority priority = CANIdentifier::CANPriority::PriorityDefault6,
TransmitCompleteCallback txCompleteCallback = nullptr,
void *parentPointer = nullptr);

/// @brief Broadcast a CAN message with the specified parameter group number and data.
/// @details This function will automatically choose an appropriate transport protocol if needed.
/// @param parameterGroupNumber The parameter group number of the CAN message.
/// @param data The data to be sent.
/// @param sourceControlFunction The source control function of the CAN message.
/// @param priority The priority of the CAN message.
/// @param txCompleteCallback The callback function to be called when the transmission is complete.
/// @param parentPointer A pointer to the parent object that gets passed to the txCompleteCallback.
/// @return True if the message is successfully enqueued, false otherwise.
bool send_can_message_global(std::uint32_t parameterGroupNumber,
std::initializer_list<std::uint8_t> data,
std::shared_ptr<InternalControlFunction> sourceControlFunction,
CANIdentifier::CANPriority priority = CANIdentifier::CANPriority::PriorityDefault6,
TransmitCompleteCallback txCompleteCallback = nullptr,
void *parentPointer = nullptr);

/// @brief This is the main function used by the stack to receive CAN messages and add them to a queue.
/// @details This function is called by the stack itself when you call can_lib_process_rx_message.
Expand Down Expand Up @@ -219,8 +355,7 @@ namespace isobus
std::uint8_t destAddress,
std::uint32_t parameterGroupNumber,
std::uint8_t priority,
const void *data,
std::uint32_t size,
DataSpan<const std::uint8_t> data,
CANLibBadge<AddressClaimStateMachine>) const;

/// @brief Processes completed protocol messages. Causes PGN callbacks to trigger.
Expand Down Expand Up @@ -269,8 +404,7 @@ namespace isobus
std::uint8_t destAddress,
std::uint32_t parameterGroupNumber,
std::uint8_t priority,
const void *data,
std::uint32_t size) const;
DataSpan<const std::uint8_t> data) const;

/// @brief Returns a control function based on a CAN address and channel index
/// @param[in] channelIndex The CAN channel index of the CAN message being processed
Expand Down Expand Up @@ -344,8 +478,7 @@ namespace isobus
std::uint8_t destAddress,
std::uint32_t parameterGroupNumber,
std::uint8_t priority,
const void *data,
std::uint32_t size) const;
DataSpan<const std::uint8_t> data) const;

/// @brief Gets a PGN callback for the global address by index
/// @param[in] index The index of the callback to get
Expand Down
Loading

0 comments on commit 32e713b

Please sign in to comment.