Skip to content

Commit

Permalink
feat: make pgn request protocol use the new message handler
Browse files Browse the repository at this point in the history
  • Loading branch information
GwnDaan committed Jul 1, 2024
1 parent bccc405 commit 13593af
Show file tree
Hide file tree
Showing 16 changed files with 94 additions and 112 deletions.
6 changes: 3 additions & 3 deletions examples/pgn_requests/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,13 @@ int main()
}

// Register a callback to handle PROPA PGN Requests
TestInternalECU->get_pgn_request_protocol().lock()->register_pgn_request_callback(static_cast<std::uint32_t>(isobus::CANLibParameterGroupNumber::ProprietaryA), example_proprietary_a_pgn_request_handler, nullptr);
TestInternalECU->get_pgn_request_protocol()->register_pgn_request_callback(static_cast<std::uint32_t>(isobus::CANLibParameterGroupNumber::ProprietaryA), example_proprietary_a_pgn_request_handler, nullptr);

// Now, if you send a PGN request for EF00 to our internal control function, the stack will acknowledge it. Other requests will be NACK'ed (negative acknowledged)
// NOTE the device you send from MUST have address claimed.

// Now we'll set up a callback to handle requests for repetition rate for the PROPA PGN
TestInternalECU->get_pgn_request_protocol().lock()->register_request_for_repetition_rate_callback(static_cast<std::uint32_t>(isobus::CANLibParameterGroupNumber::ProprietaryA), example_proprietary_a_request_for_repetition_rate_handler, nullptr);
TestInternalECU->get_pgn_request_protocol()->register_request_for_repetition_rate_callback(static_cast<std::uint32_t>(isobus::CANLibParameterGroupNumber::ProprietaryA), example_proprietary_a_request_for_repetition_rate_handler, nullptr);

// Now we'll get a callback when someone requests a repetition rate for PROPA.
// The application (not the stack) must handle these requests, as the CAN stack does not know what data to send when responding.
Expand All @@ -159,7 +159,7 @@ int main()

// This is how you would request a PGN from someone else. In this example, we request it from the broadcast address.
// Generally you'd want to replace nullptr with your partner control function as its a little nicer than just asking everyone on the bus for a PGN
isobus::ParameterGroupNumberRequestProtocol::request_parameter_group_number(static_cast<std::uint32_t>(isobus::CANLibParameterGroupNumber::ProprietaryA), TestInternalECU, nullptr);
TestInternalECU->get_pgn_request_protocol()->request_parameter_group_number(static_cast<std::uint32_t>(isobus::CANLibParameterGroupNumber::ProprietaryA), nullptr);

while (running)
{
Expand Down
1 change: 1 addition & 0 deletions examples/seeder_example/seeder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "isobus/hardware_integration/available_can_drivers.hpp"
#include "isobus/hardware_integration/can_hardware_interface.hpp"
#include "isobus/isobus/can_network_manager.hpp"
#include "isobus/isobus/isobus_diagnostic_protocol.hpp"
#include "isobus/isobus/isobus_standard_data_description_indices.hpp"
#include "isobus/isobus/isobus_task_controller_client.hpp"
Expand Down
12 changes: 7 additions & 5 deletions isobus/include/isobus/isobus/can_internal_control_function.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,12 @@ namespace isobus

/// @brief Gets the PGN request protocol for this ICF
/// @returns The PGN request protocol for this ICF
std::weak_ptr<ParameterGroupNumberRequestProtocol> get_pgn_request_protocol() const;
std::shared_ptr<ParameterGroupNumberRequestProtocol> get_pgn_request_protocol() const;

/// @brief Sets the PGN request protocol for this ICF, only use this if you have advanced needs.
/// Normally, when you create the internal control function via the network manager, it will set this for you.
/// @param[in] protocol The PGN request protocol for this ICF
void set_pgn_request_protocol(std::shared_ptr<ParameterGroupNumberRequestProtocol> protocol);

/// @brief Validates that a CAN message has not caused an address violation for this ICF.
/// If a violation is found, a re-claim will be executed for as is required by ISO 11783-5,
Expand All @@ -88,10 +93,6 @@ namespace isobus
/// @returns true if the message caused an address violation, otherwise false
bool process_rx_message_for_address_violation(const CANMessage &message);

protected:
friend class CANNetworkManager; ///< Allow the network manager to access the pgn request protocol
std::shared_ptr<ParameterGroupNumberRequestProtocol> pgnRequestProtocol; ///< The PGN request protocol for this ICF

private:
/// @brief Sends the PGN request for the address claim PGN
/// @returns true if the message was sent, otherwise false
Expand Down Expand Up @@ -119,6 +120,7 @@ namespace isobus
std::uint8_t preferredAddress; ///< The address we'd prefer to claim as (we may not get it)
std::uint8_t randomClaimDelay_ms; ///< The random delay before claiming an address as required by the ISO11783 standard
EventDispatcher<std::uint8_t> addressClaimedDispatcher; ///< The event dispatcher for when an address is claimed
std::shared_ptr<ParameterGroupNumberRequestProtocol> pgnRequestProtocol = nullptr; ///< The PGN request protocol for this ICF
};

} // namespace isobus
Expand Down
2 changes: 0 additions & 2 deletions isobus/include/isobus/isobus/can_message_handling.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,12 @@ namespace isobus
virtual ~CANMessagingConsumer() = default;

/// @brief Processes incoming CAN messages
/// @param message The incoming CAN message to process
virtual void process_rx_message(const CANMessage &)
{
// Override this function in the derived class, if you want to process incoming messages
}

/// @brief Processes outgoing CAN messages
/// @param message The outgoing CAN message to process
virtual void process_tx_message(const CANMessage &)
{
// Override this function in the derived class, if you want to process outgoing messages
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,23 @@

#include "isobus/isobus/can_badge.hpp"
#include "isobus/isobus/can_control_function.hpp"
#include "isobus/isobus/can_network_manager.hpp"
#include "isobus/isobus/can_message_handling.hpp"

#include <memory>

namespace isobus
{
//================================================================================================
/// @class ParameterGroupNumberRequestProtocol
///
/// @brief A protocol that handles PGN requests
/// @details The purpose of this protocol is to simplify and standardize how PGN requests
/// are made and responded to. It provides a way to easily send a PGN request or a request for
/// repetition rate, as well as methods to receive PGN requests.
//================================================================================================
class ParameterGroupNumberRequestProtocol
class ParameterGroupNumberRequestProtocol : public CANMessagingConsumer
{
public:
/// @brief The constructor for this protocol
/// @param[in] internalControlFunction The internal control function that owns this protocol and will be used to send messages
explicit ParameterGroupNumberRequestProtocol(std::shared_ptr<InternalControlFunction> internalControlFunction);

/// @brief The destructor for this protocol
~ParameterGroupNumberRequestProtocol();

/// @brief Remove the copy constructor
ParameterGroupNumberRequestProtocol(const ParameterGroupNumberRequestProtocol &) = delete;

Expand All @@ -45,19 +38,17 @@ namespace isobus

/// @brief Sends a PGN request to the specified control function
/// @param[in] pgn The PGN to request
/// @param[in] source The internal control function to send from
/// @param[in] destination The control function to request `pgn` from
/// @returns `true` if the request was successfully sent
static bool request_parameter_group_number(std::uint32_t pgn, std::shared_ptr<InternalControlFunction> source, std::shared_ptr<ControlFunction> destination);
bool request_parameter_group_number(std::uint32_t pgn, std::shared_ptr<ControlFunction> destination);

/// @brief Sends a PGN request for repetition rate
/// @details Use this if you want the destination CF to send you the specified PGN at some fixed interval
/// @param[in] pgn The PGN to request
/// @param[in] repetitionRate_ms The repetition rate to request in milliseconds
/// @param[in] source The internal control function to send from
/// @param[in] destination The control function to send the request to
/// @returns `true` if the request was sent
static bool request_repetition_rate(std::uint32_t pgn, std::uint16_t repetitionRate_ms, std::shared_ptr<InternalControlFunction> source, std::shared_ptr<ControlFunction> destination);
bool request_repetition_rate(std::uint32_t pgn, std::uint16_t repetitionRate_ms, std::shared_ptr<ControlFunction> destination);

/// @brief Registers for a callback on receipt of a PGN request
/// @param[in] pgn The PGN you want to handle in the callback
Expand Down Expand Up @@ -142,12 +133,7 @@ namespace isobus

/// @brief A generic way for a protocol to process a received message
/// @param[in] message A received CAN message
void process_message(const CANMessage &message);

/// @brief A generic way for a protocol to process a received message
/// @param[in] message A received CAN message
/// @param[in] parent Provides the context to the actual TP manager object
static void process_message(const CANMessage &message, void *parent);
void process_rx_message(const CANMessage &message) override;

/// @brief Sends a message using the acknowledgement PGN
/// @param[in] type The type of acknowledgement to send (Ack, vs Nack, etc)
Expand Down
2 changes: 0 additions & 2 deletions isobus/include/isobus/isobus/isobus_functionalities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@

namespace isobus
{
class DiagnosticProtocol; // Forward declaration

/// @brief Manages the control function functionalities message
class ControlFunctionFunctionalities
{
Expand Down
8 changes: 7 additions & 1 deletion isobus/src/can_internal_control_function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "isobus/isobus/can_internal_control_function.hpp"

#include "isobus/isobus/can_constants.hpp"
#include "isobus/isobus/can_network_manager.hpp"
#include "isobus/isobus/can_parameter_group_number_request_protocol.hpp"
#include "isobus/isobus/can_stack_logger.hpp"
#include "isobus/utility/system_timing.hpp"
Expand Down Expand Up @@ -300,11 +301,16 @@ namespace isobus
return addressClaimedDispatcher;
}

std::weak_ptr<ParameterGroupNumberRequestProtocol> InternalControlFunction::get_pgn_request_protocol() const
std::shared_ptr<ParameterGroupNumberRequestProtocol> InternalControlFunction::get_pgn_request_protocol() const
{
return pgnRequestProtocol;
}

void InternalControlFunction::set_pgn_request_protocol(std::shared_ptr<ParameterGroupNumberRequestProtocol> protocol)
{
pgnRequestProtocol = protocol;
}

bool InternalControlFunction::send_request_to_claim() const
{
const auto parameterGroupNumber = static_cast<std::uint32_t>(CANLibParameterGroupNumber::AddressClaim);
Expand Down
5 changes: 3 additions & 2 deletions isobus/src/can_network_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ namespace isobus
std::shared_ptr<InternalControlFunction> CANNetworkManager::create_internal_control_function(NAME desiredName, std::uint8_t CANPort, std::uint8_t preferredAddress)
{
auto controlFunction = std::make_shared<InternalControlFunction>(desiredName, preferredAddress, CANPort);
controlFunction->pgnRequestProtocol.reset(new ParameterGroupNumberRequestProtocol(controlFunction));
controlFunction->set_pgn_request_protocol(std::make_shared<ParameterGroupNumberRequestProtocol>(controlFunction));
messageHandler.add_consumer(controlFunction->get_pgn_request_protocol());
internalControlFunctions.push_back(controlFunction);
heartBeatInterfaces.at(CANPort)->on_new_internal_control_function(controlFunction);
return controlFunction;
Expand All @@ -68,7 +69,7 @@ namespace isobus
void CANNetworkManager::deactivate_control_function(std::shared_ptr<InternalControlFunction> controlFunction)
{
// We need to unregister the control function from the interfaces managed by the network manager first.
controlFunction->pgnRequestProtocol.reset();
controlFunction->set_pgn_request_protocol(nullptr);
heartBeatInterfaces.at(controlFunction->get_can_port())->on_destroyed_internal_control_function(controlFunction);
internalControlFunctions.erase(std::remove(internalControlFunctions.begin(), internalControlFunctions.end(), controlFunction), internalControlFunctions.end());
deactivate_control_function(std::static_pointer_cast<ControlFunction>(controlFunction));
Expand Down
60 changes: 21 additions & 39 deletions isobus/src/can_parameter_group_number_request_protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,24 @@ namespace isobus
myControlFunction(internalControlFunction)
{
assert(nullptr != myControlFunction && "ParameterGroupNumberRequestProtocol::ParameterGroupNumberRequestProtocol() called with nullptr internalControlFunction");
CANNetworkManager::CANNetwork.add_protocol_parameter_group_number_callback(static_cast<std::uint32_t>(CANLibParameterGroupNumber::ParameterGroupNumberRequest), process_message, this);
CANNetworkManager::CANNetwork.add_protocol_parameter_group_number_callback(static_cast<std::uint32_t>(CANLibParameterGroupNumber::RequestForRepetitionRate), process_message, this);
}

ParameterGroupNumberRequestProtocol::~ParameterGroupNumberRequestProtocol()
{
CANNetworkManager::CANNetwork.remove_protocol_parameter_group_number_callback(static_cast<std::uint32_t>(CANLibParameterGroupNumber::ParameterGroupNumberRequest), process_message, this);
CANNetworkManager::CANNetwork.remove_protocol_parameter_group_number_callback(static_cast<std::uint32_t>(CANLibParameterGroupNumber::RequestForRepetitionRate), process_message, this);
}

bool ParameterGroupNumberRequestProtocol::request_parameter_group_number(std::uint32_t pgn, std::shared_ptr<InternalControlFunction> source, std::shared_ptr<ControlFunction> destination)
bool ParameterGroupNumberRequestProtocol::request_parameter_group_number(std::uint32_t pgn, std::shared_ptr<ControlFunction> destination)
{
std::array<std::uint8_t, PGN_REQUEST_LENGTH> buffer;

buffer[0] = static_cast<std::uint8_t>(pgn & 0xFF);
buffer[1] = static_cast<std::uint8_t>((pgn >> 8) & 0xFF);
buffer[2] = static_cast<std::uint8_t>((pgn >> 16) & 0xFF);

return CANNetworkManager::CANNetwork.send_can_message(static_cast<std::uint32_t>(CANLibParameterGroupNumber::ParameterGroupNumberRequest),
buffer.data(),
PGN_REQUEST_LENGTH,
source,
destination);
return send_can_message(static_cast<std::uint32_t>(CANLibParameterGroupNumber::ParameterGroupNumberRequest),
buffer.data(),
PGN_REQUEST_LENGTH,
myControlFunction,
destination);
}

bool ParameterGroupNumberRequestProtocol::request_repetition_rate(std::uint32_t pgn, std::uint16_t repetitionRate_ms, std::shared_ptr<InternalControlFunction> source, std::shared_ptr<ControlFunction> destination)
bool ParameterGroupNumberRequestProtocol::request_repetition_rate(std::uint32_t pgn, std::uint16_t repetitionRate_ms, std::shared_ptr<ControlFunction> destination)
{
std::array<std::uint8_t, CAN_DATA_LENGTH> buffer;

Expand All @@ -61,11 +53,11 @@ namespace isobus
buffer[6] = 0xFF;
buffer[7] = 0xFF;

return CANNetworkManager::CANNetwork.send_can_message(static_cast<std::uint32_t>(CANLibParameterGroupNumber::RequestForRepetitionRate),
buffer.data(),
CAN_DATA_LENGTH,
source,
destination);
return send_can_message(static_cast<std::uint32_t>(CANLibParameterGroupNumber::RequestForRepetitionRate),
buffer.data(),
CAN_DATA_LENGTH,
myControlFunction,
destination);
}

bool ParameterGroupNumberRequestProtocol::register_pgn_request_callback(std::uint32_t pgn, PGNRequestCallback callback, void *parentPointer)
Expand Down Expand Up @@ -162,18 +154,16 @@ namespace isobus
return ((obj.callbackFunction == this->callbackFunction) && (obj.pgn == this->pgn) && (obj.parent == this->parent));
}

void ParameterGroupNumberRequestProtocol::process_message(const CANMessage &message)
void ParameterGroupNumberRequestProtocol::process_rx_message(const CANMessage &message)
{
if (((nullptr == message.get_destination_control_function()) &&
(BROADCAST_CAN_ADDRESS == message.get_identifier().get_destination_address())) ||
(message.get_destination_control_function() == myControlFunction))
if (message.is_broadcast() || message.is_destination(myControlFunction))
{
switch (message.get_identifier().get_parameter_group_number())
{
case static_cast<std::uint32_t>(CANLibParameterGroupNumber::RequestForRepetitionRate):
{
// Can't send this request to global, and must be 8 bytes. Ignore illegal message formats
if ((CAN_DATA_LENGTH == message.get_data_length()) && (nullptr != message.get_destination_control_function()))
if ((CAN_DATA_LENGTH == message.get_data_length()) && message.is_destination(myControlFunction))
{
std::uint32_t requestedPGN = message.get_uint24_at(0);
std::uint16_t requestedRate = message.get_uint16_at(3);
Expand Down Expand Up @@ -235,7 +225,7 @@ namespace isobus
}
}

if ((!anyCallbackProcessed) && (nullptr != message.get_destination_control_function()))
if ((!anyCallbackProcessed) && message.is_destination(myControlFunction))
{
send_acknowledgement(AcknowledgementType::Negative,
requestedPGN,
Expand All @@ -258,14 +248,6 @@ namespace isobus
}
}

void ParameterGroupNumberRequestProtocol::process_message(const CANMessage &message, void *parent)
{
if (nullptr != parent)
{
reinterpret_cast<ParameterGroupNumberRequestProtocol *>(parent)->process_message(message);
}
}

bool ParameterGroupNumberRequestProtocol::send_acknowledgement(AcknowledgementType type, std::uint32_t parameterGroupNumber, std::shared_ptr<ControlFunction> destination) const
{
bool retVal = false;
Expand All @@ -283,11 +265,11 @@ namespace isobus
buffer[6] = static_cast<std::uint8_t>((parameterGroupNumber >> 8) & 0xFF);
buffer[7] = static_cast<std::uint8_t>((parameterGroupNumber >> 16) & 0xFF);

retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast<std::uint32_t>(CANLibParameterGroupNumber::Acknowledge),
buffer.data(),
CAN_DATA_LENGTH,
myControlFunction,
nullptr);
retVal = send_can_message(static_cast<std::uint32_t>(CANLibParameterGroupNumber::Acknowledge),
buffer.data(),
CAN_DATA_LENGTH,
myControlFunction,
nullptr);
}
return retVal;
}
Expand Down
Loading

0 comments on commit 13593af

Please sign in to comment.