diff --git a/examples/diagnostic_protocol/main.cpp b/examples/diagnostic_protocol/main.cpp index 4f3034f7..dcb825a8 100644 --- a/examples/diagnostic_protocol/main.cpp +++ b/examples/diagnostic_protocol/main.cpp @@ -64,7 +64,7 @@ int main() TestDeviceNAME.set_device_class_instance(0); TestDeviceNAME.set_manufacturer_code(64); - auto TestInternalECU = std::make_shared(TestDeviceNAME, 0x1C, 0); + auto TestInternalECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x1C, 0); // Wait to make sure address claiming is done. The time is arbitrary. //! @todo Check this instead of asuming it is done diff --git a/examples/nmea2000/main.cpp b/examples/nmea2000/main.cpp index 8bd7d857..33b9faa9 100644 --- a/examples/nmea2000/main.cpp +++ b/examples/nmea2000/main.cpp @@ -20,8 +20,8 @@ void nmea2k_callback(const isobus::CANMessage &message, void *) void nmea2k_transmit_complete_callback(std::uint32_t parameterGroupNumber, std::uint32_t dataLength, - isobus::InternalControlFunction *, - isobus::ControlFunction *, + std::shared_ptr, + std::shared_ptr, bool successful, void *) { @@ -85,7 +85,7 @@ int main() TestDeviceNAME.set_device_class_instance(0); TestDeviceNAME.set_manufacturer_code(64); - isobus::InternalControlFunction TestInternalECU(TestDeviceNAME, 0x1C, 0); + auto TestInternalECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x1C, 0); isobus::CANNetworkManager::CANNetwork.get_fast_packet_protocol().register_multipacket_message_callback(0x1F001, nmea2k_callback, nullptr); @@ -105,7 +105,7 @@ int main() while (running) { // Send a fast packet message - isobus::CANNetworkManager::CANNetwork.get_fast_packet_protocol().send_multipacket_message(0x1F001, testMessageData, TEST_MESSAGE_LENGTH, &TestInternalECU, nullptr, isobus::CANIdentifier::PriorityLowest7, nmea2k_transmit_complete_callback); + isobus::CANNetworkManager::CANNetwork.get_fast_packet_protocol().send_multipacket_message(0x1F001, testMessageData, TEST_MESSAGE_LENGTH, TestInternalECU, nullptr, isobus::CANIdentifier::PriorityLowest7, nmea2k_transmit_complete_callback); // Sleep for a while std::this_thread::sleep_for(std::chrono::milliseconds(2000)); diff --git a/examples/pgn_requests/main.cpp b/examples/pgn_requests/main.cpp index 4969e01c..e2060637 100644 --- a/examples/pgn_requests/main.cpp +++ b/examples/pgn_requests/main.cpp @@ -13,7 +13,7 @@ //! It is discouraged to use global variables, but it is done here for simplicity. static std::uint32_t propARepetitionRate_ms = 0xFFFFFFFF; -static isobus::ControlFunction *repetitionRateRequestor = nullptr; +static std::shared_ptr repetitionRateRequestor = nullptr; static std::atomic_bool running = { true }; void signal_handler(int) @@ -22,7 +22,7 @@ void signal_handler(int) } bool example_proprietary_a_pgn_request_handler(std::uint32_t parameterGroupNumber, - isobus::ControlFunction *, + std::shared_ptr, bool &acknowledge, isobus::AcknowledgementType &acknowledgeType, void *) @@ -50,7 +50,7 @@ bool example_proprietary_a_pgn_request_handler(std::uint32_t parameterGroupNumbe } bool example_proprietary_a_request_for_repetition_rate_handler(std::uint32_t parameterGroupNumber, - isobus::ControlFunction *requestingControlFunction, + std::shared_ptr requestingControlFunction, std::uint32_t repetitionRate, void *) { @@ -125,7 +125,7 @@ int main() TestDeviceNAME.set_device_class_instance(0); TestDeviceNAME.set_manufacturer_code(64); - std::shared_ptr TestInternalECU = std::make_shared(TestDeviceNAME, 0x1C, 0); + auto TestInternalECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x1C, 0); std::signal(SIGINT, signal_handler); // Wait to make sure address claiming is done. The time is arbitrary. @@ -157,7 +157,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(isobus::CANLibParameterGroupNumber::ProprietaryA), TestInternalECU.get(), nullptr); + isobus::ParameterGroupNumberRequestProtocol::request_parameter_group_number(static_cast(isobus::CANLibParameterGroupNumber::ProprietaryA), TestInternalECU, nullptr); } while (running) @@ -166,7 +166,7 @@ int main() { // If someone has requested a repetition rate for PROPA, service it here (in the application layer) std::uint8_t buffer[isobus::CAN_DATA_LENGTH] = { 0 }; - isobus::CANNetworkManager::CANNetwork.send_can_message(static_cast(isobus::CANLibParameterGroupNumber::ProprietaryA), buffer, isobus::CAN_DATA_LENGTH, TestInternalECU.get(), repetitionRateRequestor); + isobus::CANNetworkManager::CANNetwork.send_can_message(static_cast(isobus::CANLibParameterGroupNumber::ProprietaryA), buffer, isobus::CAN_DATA_LENGTH, TestInternalECU, repetitionRateRequestor); std::this_thread::sleep_for(std::chrono::milliseconds(propARepetitionRate_ms)); } else diff --git a/examples/task_controller_client/main.cpp b/examples/task_controller_client/main.cpp index cf8f45eb..702004cc 100644 --- a/examples/task_controller_client/main.cpp +++ b/examples/task_controller_client/main.cpp @@ -76,8 +76,8 @@ int main() const isobus::NAMEFilter filterTaskController(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::TaskController)); const std::vector tcNameFilters = { filterTaskController }; - auto TestInternalECU = std::make_shared(TestDeviceNAME, 0x1C, 0); - auto TestPartnerTC = std::make_shared(0, tcNameFilters); + auto TestInternalECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x1C, 0); + auto TestPartnerTC = isobus::PartneredControlFunction::create(0, tcNameFilters); TestTCClient = std::make_shared(TestPartnerTC, TestInternalECU, nullptr); diff --git a/examples/transport_layer/main.cpp b/examples/transport_layer/main.cpp index 41538875..262abef9 100644 --- a/examples/transport_layer/main.cpp +++ b/examples/transport_layer/main.cpp @@ -70,8 +70,8 @@ int main() const isobus::NAMEFilter filterVirtualTerminal(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::VirtualTerminal)); - isobus::InternalControlFunction TestInternalECU(TestDeviceNAME, 0x1C, 0); - isobus::PartneredControlFunction TestPartner(0, { filterVirtualTerminal }); + auto TestInternalECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x1C, 0); + auto TestPartner = isobus::PartneredControlFunction::create(0, { filterVirtualTerminal }); // Wait to make sure address claiming is done. The time is arbitrary. //! @todo Check this instead of asuming it is done @@ -91,14 +91,14 @@ int main() } // Send a classic CAN message to a specific destination(8 bytes or less) - if (running && isobus::CANNetworkManager::CANNetwork.send_can_message(0xEF00, ETPTestBuffer, isobus::CAN_DATA_LENGTH, &TestInternalECU, &TestPartner)) + if (running && isobus::CANNetworkManager::CANNetwork.send_can_message(0xEF00, ETPTestBuffer, isobus::CAN_DATA_LENGTH, TestInternalECU, TestPartner)) { std::cout << "Sent a normal CAN Message with length 8" << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(4)); // Arbitrary } // 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(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 @@ -115,7 +115,7 @@ int main() } // Send message - if (isobus::CANNetworkManager::CANNetwork.send_can_message(0xEF00, TPTestBuffer, i, &TestInternalECU, &TestPartner)) + if (isobus::CANNetworkManager::CANNetwork.send_can_message(0xEF00, TPTestBuffer, i, TestInternalECU, TestPartner)) { std::cout << "Started TP CM Session with length " << i << std::endl; } @@ -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(0xEF00, TPTestBuffer, i, TestInternalECU)) { std::cout << "Started BAM Session with length " << i << std::endl; } @@ -153,7 +153,7 @@ int main() // ETP Example // Send one ETP message - if (running && isobus::CANNetworkManager::CANNetwork.send_can_message(0xEF00, ETPTestBuffer, ETP_TEST_SIZE, &TestInternalECU, &TestPartner)) + if (running && isobus::CANNetworkManager::CANNetwork.send_can_message(0xEF00, ETPTestBuffer, ETP_TEST_SIZE, TestInternalECU, TestPartner)) { std::cout << "Started ETP Session with length " << ETP_TEST_SIZE << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(2000)); diff --git a/examples/virtual_terminal/aux_functions/main.cpp b/examples/virtual_terminal/aux_functions/main.cpp index 504b0db5..f1efffa8 100644 --- a/examples/virtual_terminal/aux_functions/main.cpp +++ b/examples/virtual_terminal/aux_functions/main.cpp @@ -95,8 +95,8 @@ int main() const isobus::NAMEFilter filterVirtualTerminal(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::VirtualTerminal)); const std::vector vtNameFilters = { filterVirtualTerminal }; - auto TestInternalECU = std::make_shared(TestDeviceNAME, 0x1D, 0); - auto TestPartnerVT = std::make_shared(0, vtNameFilters); + auto TestInternalECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x1D, 0); + auto TestPartnerVT = isobus::PartneredControlFunction::create(0, vtNameFilters); TestVirtualTerminalClient = std::make_shared(TestPartnerVT, TestInternalECU); TestVirtualTerminalClient->set_object_pool(0, isobus::VirtualTerminalClient::VTVersion::Version3, testPool.data(), testPool.size(), objectPoolHash); diff --git a/examples/virtual_terminal/aux_inputs/main.cpp b/examples/virtual_terminal/aux_inputs/main.cpp index 863e7ace..e44e07f9 100644 --- a/examples/virtual_terminal/aux_inputs/main.cpp +++ b/examples/virtual_terminal/aux_inputs/main.cpp @@ -158,8 +158,8 @@ int main() const isobus::NAMEFilter filterVirtualTerminal(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::VirtualTerminal)); const std::vector vtNameFilters = { filterVirtualTerminal }; - auto TestInternalECU = std::make_shared(TestDeviceNAME, 0x1E, 0); - auto TestPartnerVT = std::make_shared(0, vtNameFilters); + auto TestInternalECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x1E, 0); + auto TestPartnerVT = isobus::PartneredControlFunction::create(0, vtNameFilters); TestVirtualTerminalClient = std::make_shared(TestPartnerVT, TestInternalECU); TestVirtualTerminalClient->set_object_pool(0, isobus::VirtualTerminalClient::VTVersion::Version3, testPool.data(), testPool.size(), objectPoolHash); diff --git a/examples/virtual_terminal/version3_object_pool/main.cpp b/examples/virtual_terminal/version3_object_pool/main.cpp index 35679118..764afde4 100644 --- a/examples/virtual_terminal/version3_object_pool/main.cpp +++ b/examples/virtual_terminal/version3_object_pool/main.cpp @@ -134,8 +134,8 @@ int main() const isobus::NAMEFilter filterVirtualTerminal(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::VirtualTerminal)); const std::vector vtNameFilters = { filterVirtualTerminal }; - auto TestInternalECU = std::make_shared(TestDeviceNAME, 0x1C, 0); - auto TestPartnerVT = std::make_shared(0, vtNameFilters); + auto TestInternalECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x1C, 0); + auto TestPartnerVT = isobus::PartneredControlFunction::create(0, vtNameFilters); TestVirtualTerminalClient = std::make_shared(TestPartnerVT, TestInternalECU); TestVirtualTerminalClient->set_object_pool(0, isobus::VirtualTerminalClient::VTVersion::Version3, testPool.data(), testPool.size(), objectPoolHash); diff --git a/isobus/include/isobus/isobus/can_callbacks.hpp b/isobus/include/isobus/isobus/can_callbacks.hpp index a9a05737..47c71086 100644 --- a/isobus/include/isobus/isobus/can_callbacks.hpp +++ b/isobus/include/isobus/isobus/can_callbacks.hpp @@ -38,19 +38,19 @@ namespace isobus /// @brief A callback for when a transmit is completed by the stack using TransmitCompleteCallback = void (*)(std::uint32_t parameterGroupNumber, std::uint32_t dataLength, - InternalControlFunction *sourceControlFunction, - ControlFunction *destinationControlFunction, + std::shared_ptr sourceControlFunction, + std::shared_ptr destinationControlFunction, bool successful, void *parentPointer); /// @brief A callback for handling a PGN request using PGNRequestCallback = bool (*)(std::uint32_t parameterGroupNumber, - ControlFunction *requestingControlFunction, + std::shared_ptr requestingControlFunction, bool &acknowledge, AcknowledgementType &acknowledgeType, void *parentPointer); /// @brief A callback for handling a request for repetition rate for a specific PGN using PGNRequestForRepetitionRateCallback = bool (*)(std::uint32_t parameterGroupNumber, - ControlFunction *requestingControlFunction, + std::shared_ptr requestingControlFunction, std::uint32_t repetitionRate, void *parentPointer); @@ -67,7 +67,7 @@ namespace isobus /// @param[in] callback The function you want the stack to call when it gets receives a message with a matching PGN /// @param[in] parentPointer A generic variable that can provide context to which object the callback was meant for /// @param[in] internalControlFunction An internal control function to use as an additional filter for the callback - ParameterGroupNumberCallbackData(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parentPointer, InternalControlFunction *internalControlFunction); + ParameterGroupNumberCallbackData(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parentPointer, std::shared_ptr internalControlFunction); /// @brief A copy constructor for holding callback data /// @param[in] oldObj The object to copy from @@ -96,13 +96,13 @@ namespace isobus /// @brief Returns the ICF being used as a filter for this callback /// @returns A pointer to the ICF being used as a filter, or nullptr - InternalControlFunction *get_internal_control_function() const; + std::shared_ptr get_internal_control_function() const; private: CANLibCallback mCallback; ///< The callback that will get called when a matching PGN is received std::uint32_t mParameterGroupNumber; ///< The PGN assocuiated with this callback void *mParent; ///< A generic variable that can provide context to which object the callback was meant for - InternalControlFunction *mInternalControlFunctionFilter; ///< An optional way to filter callbacks based on the destination of messages from the partner + std::shared_ptr mInternalControlFunctionFilter; ///< An optional way to filter callbacks based on the destination of messages from the partner }; } // namespace isobus diff --git a/isobus/include/isobus/isobus/can_control_function.hpp b/isobus/include/isobus/isobus/can_control_function.hpp index 6dad3003..369a5925 100644 --- a/isobus/include/isobus/isobus/can_control_function.hpp +++ b/isobus/include/isobus/isobus/can_control_function.hpp @@ -3,6 +3,7 @@ /// /// @brief Defines a base class to represent a generic ISOBUS control function. /// @author Adrian Del Grosso +/// @author Daan Steenbergen /// /// @copyright 2022 Adrian Del Grosso //================================================================================================ @@ -12,6 +13,7 @@ #include "isobus/isobus/can_NAME.hpp" +#include #include namespace isobus @@ -21,7 +23,7 @@ namespace isobus /// /// @brief A class that describes an ISO11783 control function, which includes a NAME and address. //================================================================================================ - class ControlFunction + class ControlFunction : public std::enable_shared_from_this { public: /// @brief The type of the control function @@ -32,14 +34,18 @@ namespace isobus Partnered ///< An external control function that you explicitly want to talk to }; - /// @brief The base class constructor for a control function + virtual ~ControlFunction() = default; + + /// @brief The factory function to construct a control function /// @param[in] NAMEValue The NAME of the control function /// @param[in] addressValue The current address of the control function /// @param[in] CANPort The CAN channel index that the control function communicates on - ControlFunction(NAME NAMEValue, std::uint8_t addressValue, std::uint8_t CANPort); + static std::shared_ptr create(NAME NAMEValue, std::uint8_t addressValue, std::uint8_t CANPort); - /// @brief The base class destructor for a control function - virtual ~ControlFunction(); + /// @brief Destroys this control function, by removing it from the network manager + /// @param[in] expectedRefCount The expected number of shared pointers to this control function after removal + /// @returns true if the control function was successfully removed from everywhere in the stack, otherwise false + virtual bool destroy(std::uint32_t expectedRefCount = 1); /// @brief Returns the current address of the control function /// @returns The current address of the control function @@ -61,13 +67,23 @@ namespace isobus /// @returns The control function type Type get_type() const; + ///@brief Returns the 'Type' of the control function as a string + ///@returns The control function type as a string + std::string get_type_string() const; + protected: + /// @brief The protected constructor for the control function, which is called by the (inherited) factory function + /// @param[in] NAMEValue The NAME of the control function + /// @param[in] addressValue The current address of the control function + /// @param[in] CANPort The CAN channel index that the control function communicates on + ControlFunction(NAME NAMEValue, std::uint8_t addressValue, std::uint8_t CANPort, Type type = Type::External); + friend class CANNetworkManager; static std::mutex controlFunctionProcessingMutex; ///< Protects the control function tables + const Type controlFunctionType; ///< The Type of the control function NAME controlFunctionNAME; ///< The NAME of the control function - Type controlFunctionType; ///< The Type of the control function std::uint8_t address; ///< The address of the control function - std::uint8_t canPortIndex; ///< The CAN channel index of the control function + const std::uint8_t canPortIndex; ///< The CAN channel index of the control function }; } // namespace isobus diff --git a/isobus/include/isobus/isobus/can_extended_transport_protocol.hpp b/isobus/include/isobus/isobus/can_extended_transport_protocol.hpp index 035661b5..6376f542 100644 --- a/isobus/include/isobus/isobus/can_extended_transport_protocol.hpp +++ b/isobus/include/isobus/isobus/can_extended_transport_protocol.hpp @@ -140,8 +140,8 @@ namespace isobus bool protocol_transmit_message(std::uint32_t parameterGroupNumber, const std::uint8_t *data, std::uint32_t messageLength, - ControlFunction *source, - ControlFunction *destination, + std::shared_ptr source, + std::shared_ptr destination, TransmitCompleteCallback transmitCompleteCallback, void *parentPointer, DataChunkCallback frameChunkCallback) override; @@ -175,7 +175,7 @@ namespace isobus /// @param[in] reason The reason we're aborting the session /// @param[in] source The source control function from which we'll send the abort /// @param[in] destination The destination control function to which we'll send the abort - bool abort_session(std::uint32_t parameterGroupNumber, ConnectionAbortReason reason, InternalControlFunction *source, ControlFunction *destination); + bool abort_session(std::uint32_t parameterGroupNumber, ConnectionAbortReason reason, std::shared_ptr source, std::shared_ptr destination); /// @brief Gracefully closes a session to prepare for a new session /// @param[in] session The session to close @@ -186,14 +186,14 @@ namespace isobus /// @param[in] source The source control function for the session /// @param[in] destination The destination control function for the session /// @param[out] session The found session, or nullptr if no session matched the supplied parameters - bool get_session(ExtendedTransportProtocolSession *&session, ControlFunction *source, ControlFunction *destination) const; + bool get_session(ExtendedTransportProtocolSession *&session, std::shared_ptr source, std::shared_ptr destination) const; /// @brief Gets an ETP session from the passed in source and destination and PGN combination /// @param[in] source The source control function for the session /// @param[in] destination The destination control function for the session /// @param[in] parameterGroupNumber The PGN of the session /// @param[out] session The found session, or nullptr if no session matched the supplied parameters - bool get_session(ExtendedTransportProtocolSession *&session, ControlFunction *source, ControlFunction *destination, std::uint32_t parameterGroupNumber) const; + bool get_session(ExtendedTransportProtocolSession *&session, std::shared_ptr source, std::shared_ptr destination, std::uint32_t parameterGroupNumber) const; /// @brief Processes end of session callbacks /// @param[in] session The session we've just completed diff --git a/isobus/include/isobus/isobus/can_internal_control_function.hpp b/isobus/include/isobus/isobus/can_internal_control_function.hpp index 50f11846..9674573c 100644 --- a/isobus/include/isobus/isobus/can_internal_control_function.hpp +++ b/isobus/include/isobus/isobus/can_internal_control_function.hpp @@ -4,6 +4,7 @@ /// @brief A representation of an ISOBUS ECU that we can send from. Use this class /// when defining your own control functions that will claim an address within your program. /// @author Adrian Del Grosso +/// @author Daan Steenbergen /// /// @copyright 2022 Adrian Del Grosso //================================================================================================ @@ -32,19 +33,21 @@ namespace isobus class InternalControlFunction : public ControlFunction { public: - /// @brief Constructor for an internal control function + /// @brief The factory function to construct an internal control function /// @param[in] desiredName The NAME for this control function to claim as /// @param[in] preferredAddress The preferred NAME for this control function /// @param[in] CANPort The CAN channel index for this control function to use - InternalControlFunction(NAME desiredName, std::uint8_t preferredAddress, std::uint8_t CANPort); + static std::shared_ptr create(NAME desiredName, std::uint8_t preferredAddress, std::uint8_t CANPort); - /// @brief Destructor for an internal control function - ~InternalControlFunction(); + /// @brief Destroys this internal control function, by removing it from the network manager + /// @param[in] expectedRefCount The expected number of shared pointers to this control function after removal + /// @returns true if the internal control function was successfully removed from everywhere in the stack, otherwise false + bool destroy(std::uint32_t expectedRefCount = 1) override; /// @brief Returns a an internal control function from the list of all internal control functions /// @param[in] index The index in the list internalControlFunctionList from which to get an ICF /// @returns The requested internal control function or `nullptr` if the index is out of range - static InternalControlFunction *get_internal_control_function(std::uint32_t index); + static std::shared_ptr get_internal_control_function(std::uint32_t index); /// @brief Returns the number of internal control functions that exist static std::uint32_t get_number_internal_control_functions(); @@ -66,11 +69,18 @@ namespace isobus /// @brief Updates all address claim state machines static void update_address_claiming(CANLibBadge); + protected: + /// @brief The protected constructor for the internal control function, which is called by the (inherited) factory function + /// @param[in] desiredName The NAME for this control function to claim as + /// @param[in] preferredAddress The preferred NAME for this control function + /// @param[in] CANPort The CAN channel index for this control function to use + InternalControlFunction(NAME desiredName, std::uint8_t preferredAddress, std::uint8_t CANPort); + private: /// @brief Updates the internal control function, should be called periodically by the network manager void update(); - static std::vector internalControlFunctionList; ///< A list of all internal control functions that exist + static std::vector> internalControlFunctionList; ///< A list of all internal control functions that exist static bool anyChangedAddress; ///< Lets the network manager know if any ICF changed address since the last update AddressClaimStateMachine stateMachine; ///< The address claimer for this ICF bool objectChangedAddressSinceLastUpdate; ///< Tracks if this object has changed address since the last update diff --git a/isobus/include/isobus/isobus/can_message.hpp b/isobus/include/isobus/isobus/can_message.hpp index 6bfe6d82..30027651 100644 --- a/isobus/include/isobus/isobus/can_message.hpp +++ b/isobus/include/isobus/isobus/can_message.hpp @@ -68,11 +68,11 @@ namespace isobus /// @brief Gets the source control function that the message is from /// @returns The source control function that the message is from - ControlFunction *get_source_control_function() const; + std::shared_ptr get_source_control_function() const; /// @brief Gets the destination control function that the message is to /// @returns The destination control function that the message is to - ControlFunction *get_destination_control_function() const; + std::shared_ptr get_destination_control_function() const; /// @brief Returns the identifier of the message /// @returns The identifier of the message @@ -98,11 +98,11 @@ namespace isobus /// @brief Sets the source control function for the message /// @param[in] value The source control function - void set_source_control_function(ControlFunction *value); + void set_source_control_function(std::shared_ptr value); /// @brief Sets the destination control function for the message /// @param[in] value The destination control function - void set_destination_control_function(ControlFunction *value); + void set_destination_control_function(std::shared_ptr value); /// @brief Sets the CAN ID of the message /// @param[in] value The CAN ID for the message @@ -159,8 +159,8 @@ namespace isobus Type messageType = Type::Receive; ///< The internal message type associated with the message CANIdentifier identifier = CANIdentifier(0); ///< The CAN ID of the message std::vector data; ///< A data buffer for the message, used when not using data chunk callbacks - ControlFunction *source = nullptr; ///< The source control function of the message - ControlFunction *destination = nullptr; ///< The destination control function of the message + std::shared_ptr source = nullptr; ///< The source control function of the message + std::shared_ptr destination = nullptr; ///< The destination control function of the message const std::uint8_t CANPortIndex; ///< The CAN channel index associated with the message }; diff --git a/isobus/include/isobus/isobus/can_network_manager.hpp b/isobus/include/isobus/isobus/can_network_manager.hpp index 7d4f9ac7..ccd7dd11 100644 --- a/isobus/include/isobus/isobus/can_network_manager.hpp +++ b/isobus/include/isobus/isobus/can_network_manager.hpp @@ -4,6 +4,7 @@ /// @brief The main class that manages the ISOBUS stack including: callbacks, Name to Address /// management, making control functions, and driving the various protocols. /// @author Adrian Del Grosso +/// @author Daan Steenbergen /// /// @copyright 2022 Adrian Del Grosso //================================================================================================ @@ -26,9 +27,10 @@ #include #include #include +#include #include -/// @brief This namespace encompases all of the ISO11783 stack's functionality to reduce global namespace pollution +/// @brief This namespace encompasses all of the ISO11783 stack's functionality to reduce global namespace pollution namespace isobus { class PartneredControlFunction; @@ -48,20 +50,20 @@ namespace isobus void initialize(); /// @brief Called only by the stack, returns a control function based on certain port and address - /// @param[in] CANPort CAN Channel index of the control function - /// @param[in] CFAddress Address of the control function + /// @param[in] channelIndex CAN Channel index of the control function + /// @param[in] address Address of the control function /// @returns A control function that matches the parameters, or nullptr if no match was found - ControlFunction *get_control_function(std::uint8_t CANPort, std::uint8_t CFAddress, CANLibBadge) const; + std::shared_ptr get_control_function(std::uint8_t channelIndex, std::uint8_t address, CANLibBadge) const; - /// @brief Called only by the stack, adds a new contorl function with specified parameters - /// @param[in] CANPort The CAN channel index associated with the control function + /// @brief Called only by the stack, adds a new control function with specified parameters + /// @param[in] channelIndex The CAN channel index associated with the control function /// @param[in] newControlFunction The new control function to be processed - /// @param[in] CFAddress The new control function's address - void add_control_function(std::uint8_t CANPort, ControlFunction *newControlFunction, std::uint8_t CFAddress, CANLibBadge); + /// @param[in] address The new control function's address + void add_control_function(std::uint8_t channelIndex, std::shared_ptr newControlFunction, std::uint8_t address, CANLibBadge); /// @brief This is how you register a callback for any PGN destined for the global address (0xFF) /// @param[in] parameterGroupNumber The PGN you want to register for - /// @param[in] callback The callback that will be called when parameterGroupNumber is recieved from the global address (0xFF) + /// @param[in] callback The callback that will be called when parameterGroupNumber is received from the global address (0xFF) /// @param[in] parent A generic context variable that helps identify what object the callback is destined for. Can be nullptr if you don't want to use it. void add_global_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent); @@ -77,7 +79,7 @@ namespace isobus /// @brief Registers a callback for ANY control function sending the associated PGN /// @param[in] parameterGroupNumber The PGN you want to register for - /// @param[in] callback The callback that will be called when parameterGroupNumber is recieved from any control function + /// @param[in] callback The callback that will be called when parameterGroupNumber is received from any control function /// @param[in] parent A generic context variable that helps identify what object the callback is destined for. Can be nullptr if you don't want to use it. void add_any_control_function_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent); @@ -89,7 +91,7 @@ namespace isobus /// @brief Returns an internal control function if the passed-in control function is an internal type /// @returns An internal control function casted from the passed in control function - InternalControlFunction *get_internal_control_function(ControlFunction *controlFunction); + std::shared_ptr get_internal_control_function(std::shared_ptr controlFunction); /// @brief Returns an estimated busload between 0.0f and 100.0f /// @details This calculates busload over a 1 second window. @@ -109,8 +111,8 @@ namespace isobus bool send_can_message(std::uint32_t parameterGroupNumber, const std::uint8_t *dataBuffer, std::uint32_t dataLength, - InternalControlFunction *sourceControlFunction, - ControlFunction *destinationControlFunction = nullptr, + std::shared_ptr sourceControlFunction, + std::shared_ptr destinationControlFunction = nullptr, CANIdentifier::CANPriority priority = CANIdentifier::CANPriority::PriorityDefault6, TransmitCompleteCallback txCompleteCallback = nullptr, void *parentPointer = nullptr, @@ -133,9 +135,13 @@ namespace isobus /// @param[in] txFrame The frame that was just emitted onto the bus static void process_transmitted_can_message_frame(const CANMessageFrame &txFrame); - /// @brief Informs the network manager that a partner was deleted so that it can be purged from the address/cf tables - /// @param[in] partner Pointer to the partner being deleted - void on_partner_deleted(PartneredControlFunction *partner, CANLibBadge); + /// @brief Informs the network manager that a control function object has been destroyed, so that it can be purged from the network manager + /// @param[in] controlFunction The control function that was destroyed + void on_control_function_destroyed(std::shared_ptr controlFunction, CANLibBadge); + + /// @brief Informs the network manager that a control function object has been created, so that it can be added to the network manager + /// @param[in] controlFunction The control function that was created + void on_control_function_created(std::shared_ptr controlFunction, CANLibBadge); /// @brief Returns the class instance of the NMEA2k fast packet protocol. /// Use this to register for FP multipacket messages @@ -199,9 +205,9 @@ namespace isobus void update_address_table(const CANMessage &message); /// @brief Updates the internal address table based on a received address claim - /// @param[in] CANPort The CAN channel index of the CAN message being processed + /// @param[in] channelIndex The CAN channel index of the CAN message being processed /// @param[in] claimedAddress The address claimed - void update_address_table(std::uint8_t CANPort, std::uint8_t claimedAddress); + void update_address_table(std::uint8_t channelIndex, std::uint8_t claimedAddress); /// @brief Processes a CAN message's contribution to the current busload /// @param[in] channelIndex The CAN channel index associated to the message being processed @@ -236,10 +242,10 @@ namespace isobus std::uint32_t size) const; /// @brief Returns a control function based on a CAN address and channel index - /// @param[in] CANPort The CAN channel index of the CAN message being processed - /// @param[in] CFAddress The CAN address associated with a control function + /// @param[in] channelIndex The CAN channel index of the CAN message being processed + /// @param[in] address The CAN address associated with a control function /// @returns A control function matching the address and CAN port passed in - ControlFunction *get_control_function(std::uint8_t CANPort, std::uint8_t CFAddress) const; + std::shared_ptr get_control_function(std::uint8_t channelIndex, std::uint8_t address) const; /// @brief Gets a message from the Rx Queue. /// @note This will only ever get an 8 byte message. Long messages are handled elsewhere. @@ -303,9 +309,8 @@ namespace isobus std::array, CAN_PORT_MAXIMUM> busloadMessageBitsHistory; ///< Stores the approximate number of bits processed on each channel over multiple previous time windows std::array currentBusloadBitAccumulator; ///< Accumulates the approximate number of bits processed on each channel during the current time window - std::array, CAN_PORT_MAXIMUM> controlFunctionTable; ///< Table to maintain address to NAME mappings - std::vector activeControlFunctions; ///< A list of active control function used to track connected devices - std::vector inactiveControlFunctions; ///< A list of inactive control functions, used to track disconnected devices + std::array, NULL_CAN_ADDRESS>, CAN_PORT_MAXIMUM> controlFunctionTable; ///< Table to maintain address to NAME mappings + std::vector> inactiveControlFunctions; ///< A list of the control function that currently don't have a valid address std::list protocolPGNCallbacks; ///< A list of PGN callback registered by CAN protocols std::list receiveMessageList; ///< A queue of Rx messages to process std::vector globalParameterGroupNumberCallbacks; ///< A list of all global PGN callbacks diff --git a/isobus/include/isobus/isobus/can_parameter_group_number_request_protocol.hpp b/isobus/include/isobus/isobus/can_parameter_group_number_request_protocol.hpp index c69ee728..f2634c80 100644 --- a/isobus/include/isobus/isobus/can_parameter_group_number_request_protocol.hpp +++ b/isobus/include/isobus/isobus/can_parameter_group_number_request_protocol.hpp @@ -54,7 +54,7 @@ namespace isobus /// @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, InternalControlFunction *source, ControlFunction *destination); + static bool request_parameter_group_number(std::uint32_t pgn, std::shared_ptr source, std::shared_ptr destination); /// @brief Sends a PGN request for repitition rate /// @details Use this if you want the requestee to send you the specified PGN at some fixed interval @@ -63,7 +63,7 @@ namespace isobus /// @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, InternalControlFunction *source, ControlFunction *destination); + static bool request_repetition_rate(std::uint32_t pgn, std::uint16_t repetitionRate_ms, std::shared_ptr source, std::shared_ptr destination); /// @brief Registers for a callback on receipt of a PGN request /// @param[in] pgn The PGN you want to handle in the callback @@ -179,8 +179,8 @@ namespace isobus bool protocol_transmit_message(std::uint32_t parameterGroupNumber, const std::uint8_t *data, std::uint32_t messageLength, - ControlFunction *source, - ControlFunction *destination, + std::shared_ptr source, + std::shared_ptr destination, TransmitCompleteCallback transmitCompleteCallback, void *parentPointer, DataChunkCallback frameChunkCallback) override; @@ -191,7 +191,7 @@ namespace isobus /// @param[in] source The source control function to send from /// @param[in] destination The destination control function to send the acknowledgement to /// @returns true if the message was sent, false otherwise - bool send_acknowledgement(AcknowledgementType type, std::uint32_t parameterGroupNumber, InternalControlFunction *source, ControlFunction *destination); + bool send_acknowledgement(AcknowledgementType type, std::uint32_t parameterGroupNumber, std::shared_ptr source, std::shared_ptr destination); static std::list pgnRequestProtocolList; ///< List of all PGN request protocol instances (one per ICF) diff --git a/isobus/include/isobus/isobus/can_partnered_control_function.hpp b/isobus/include/isobus/isobus/can_partnered_control_function.hpp index 767547d7..20a77374 100644 --- a/isobus/include/isobus/isobus/can_partnered_control_function.hpp +++ b/isobus/include/isobus/isobus/can_partnered_control_function.hpp @@ -4,6 +4,7 @@ /// @brief A class that describes a control function on the bus that the stack should communicate /// with. Use these to describe ECUs you want to send messages to. /// @author Adrian Del Grosso +/// @author Daan Steenbergen /// /// @copyright 2022 Adrian Del Grosso //================================================================================================ @@ -27,7 +28,7 @@ namespace isobus //================================================================================================ /// @class PartneredControlFunction /// - /// @brief This reprents any device on the bus you want to talk to. + /// @brief This represents any device on the bus you want to talk to. /// @details To communicate with a device on the bus, create one of these objects and tell it /// via the constructor what the identity of that device is using NAME fields like /// manufacturer code, function, and device class. The stack will take care of locating the @@ -37,16 +38,18 @@ namespace isobus class PartneredControlFunction : public ControlFunction { public: - /// @brief the constructor for a PartneredControlFunction + /// @brief The factory function to construct a partnered control function /// @param[in] CANPort The CAN channel associated with this control function definition /// @param[in] NAMEFilters A list of filters that describe the identity of the CF based on NAME components - PartneredControlFunction(std::uint8_t CANPort, const std::vector NAMEFilters); + static std::shared_ptr create(std::uint8_t CANPort, const std::vector NAMEFilters); /// @brief Deleted copy constructor for PartneredControlFunction to avoid slicing PartneredControlFunction(PartneredControlFunction &) = delete; - /// @brief The destructor for PartneredControlFunction - virtual ~PartneredControlFunction(); + /// @brief Destroys this partnered control function, by removing it from the network manager + /// @param[in] expectedRefCount The expected number of shared pointers to this control function after removal + /// @returns true if the partnered control function was successfully removed from everywhere in the stack, otherwise false + bool destroy(std::uint32_t expectedRefCount = 1) override; /// @brief This is how you get notified that this control function has sent you a destination specific message. /// @details Add a callback function here to be notified when this device has sent you a message with the specified PGN. @@ -61,14 +64,14 @@ namespace isobus /// @param[in] internalControlFunction An internal control function to filter based on. If you supply this /// parameter the callback will only be called when messages from the partner are received with the /// specified ICF as the destination. - void add_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, InternalControlFunction *internalControlFunction = nullptr); + void add_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, std::shared_ptr internalControlFunction = nullptr); /// @brief Removes a callback matching *exactly* the parameters passed in /// @param[in] parameterGroupNumber The PGN associated with the callback being removed /// @param[in] callback The callback function being removed /// @param[in] parent A generic context variable that helps identify what object the callback was destined for /// @param[in] internalControlFunction The ICF being used to filter messages against - void remove_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, InternalControlFunction *internalControlFunction = nullptr); + void remove_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, std::shared_ptr internalControlFunction = nullptr); /// @brief Returns the number of parameter group number callbacks associated with this control function /// @returns The number of parameter group number callbacks associated with this control function @@ -98,7 +101,7 @@ namespace isobus /// @brief Gets a PartneredControlFunction by index /// @param[in] index The index of the PartneredControlFunction to get /// @returns a PartneredControlFunction at the index specified from `partneredControlFunctionList` - static PartneredControlFunction *get_partnered_control_function(std::size_t index); + static std::shared_ptr get_partnered_control_function(std::size_t index); /// @brief Returns the number of created partner control functions /// @returns The number of created partner control functions from the static list of all of them @@ -107,16 +110,24 @@ namespace isobus private: friend class CANNetworkManager; ///< Allows the network manager to use get_parameter_group_number_callback + /// @brief the constructor for a PartneredControlFunction, which is called by the factory function + /// @param[in] CANPort The CAN channel associated with this control function definition + /// @param[in] NAMEFilters A list of filters that describe the identity of the CF based on NAME components + PartneredControlFunction(std::uint8_t CANPort, const std::vector NAMEFilters); + + /// @brief Make inherited factory function private so that it can't be called + static std::shared_ptr create(NAME NAMEValue, std::uint8_t addressValue, std::uint8_t CANPort) = delete; + /// @brief Returns a parameter group number associated with this control function by index /// @param[in] index The index from which to get the PGN callback data object /// @returns A reference to the PGN callback data object at the index specified ParameterGroupNumberCallbackData &get_parameter_group_number_callback(std::size_t index); - static std::vector partneredControlFunctionList; ///< A list of all created partnered control functions + static std::vector> partneredControlFunctionList; ///< A list of all created partnered control functions static bool anyPartnerNeedsInitializing; ///< A way for the network manager to know if it needs to parse the partner list to match partners with existing CFs const std::vector NAMEFilterList; ///< A list of NAME parameters that describe this control function's identity std::vector parameterGroupNumberCallbacks; ///< A list of all parameter group number callbacks associated with this control function - bool initialized; ///< A way to track if the network manager has processed this CF against existing CFs + bool initialized = false; ///< A way to track if the network manager has processed this CF against existing CFs }; } // namespace isobus diff --git a/isobus/include/isobus/isobus/can_protocol.hpp b/isobus/include/isobus/isobus/can_protocol.hpp index 100f33e8..7742e1f5 100644 --- a/isobus/include/isobus/isobus/can_protocol.hpp +++ b/isobus/include/isobus/isobus/can_protocol.hpp @@ -77,8 +77,8 @@ namespace isobus virtual bool protocol_transmit_message(std::uint32_t parameterGroupNumber, const std::uint8_t *data, std::uint32_t messageLength, - ControlFunction *source, - ControlFunction *destination, + std::shared_ptr source, + std::shared_ptr destination, TransmitCompleteCallback transmitCompleteCallback, void *parentPointer, DataChunkCallback frameChunkCallback) = 0; diff --git a/isobus/include/isobus/isobus/can_transport_protocol.hpp b/isobus/include/isobus/isobus/can_transport_protocol.hpp index 98b1aeec..8071961a 100644 --- a/isobus/include/isobus/isobus/can_transport_protocol.hpp +++ b/isobus/include/isobus/isobus/can_transport_protocol.hpp @@ -153,8 +153,8 @@ namespace isobus bool protocol_transmit_message(std::uint32_t parameterGroupNumber, const std::uint8_t *data, std::uint32_t messageLength, - ControlFunction *source, - ControlFunction *destination, + std::shared_ptr source, + std::shared_ptr destination, TransmitCompleteCallback transmitCompleteCallback, void *parentPointer, DataChunkCallback frameChunkCallback) override; @@ -175,7 +175,7 @@ namespace isobus /// @param[in] source The source control function from which we'll send the abort /// @param[in] destination The destination control function to which we'll send the abort /// @returns true if the abort was send OK, false if not sent - bool abort_session(std::uint32_t parameterGroupNumber, ConnectionAbortReason reason, InternalControlFunction *source, ControlFunction *destination); + bool abort_session(std::uint32_t parameterGroupNumber, ConnectionAbortReason reason, std::shared_ptr source, std::shared_ptr destination); /// @brief Gracefully closes a session to prepare for a new session /// @param[in] session The session to close @@ -216,14 +216,14 @@ namespace isobus /// @param[in] source The source control function for the session /// @param[in] destination The destination control function for the session /// @param[out] session The found session, or nullptr if no session matched the supplied parameters - bool get_session(TransportProtocolSession *&session, ControlFunction *source, ControlFunction *destination); + bool get_session(TransportProtocolSession *&session, std::shared_ptr source, std::shared_ptr destination); /// @brief Gets a TP session from the passed in source and destination and PGN combination /// @param[in] source The source control function for the session /// @param[in] destination The destination control function for the session /// @param[in] parameterGroupNumber The PGN of the session /// @param[out] session The found session, or nullptr if no session matched the supplied parameters - bool get_session(TransportProtocolSession *&session, ControlFunction *source, ControlFunction *destination, std::uint32_t parameterGroupNumber); + bool get_session(TransportProtocolSession *&session, std::shared_ptr source, std::shared_ptr destination, std::uint32_t parameterGroupNumber); /// @brief Updates the state machine of a Tp session /// @param[in] session The session to update diff --git a/isobus/include/isobus/isobus/isobus_diagnostic_protocol.hpp b/isobus/include/isobus/isobus/isobus_diagnostic_protocol.hpp index 33407429..fb68bd67 100644 --- a/isobus/include/isobus/isobus/isobus_diagnostic_protocol.hpp +++ b/isobus/include/isobus/isobus/isobus_diagnostic_protocol.hpp @@ -325,7 +325,7 @@ namespace isobus /// @param[in] sourceControlFunction The internal control function to send the DM13 from /// @param[in] suspendTime_seconds If you know the time for which broadcasts will be suspended, put it here, otherwise 0xFFFF /// @returns `true` if the message was sent, otherwise `false` - bool suspend_broadcasts(std::uint8_t canChannelIndex, InternalControlFunction *sourceControlFunction, std::uint16_t suspendTime_seconds = 0xFFFF); + bool suspend_broadcasts(std::uint8_t canChannelIndex, std::shared_ptr sourceControlFunction, std::uint16_t suspendTime_seconds = 0xFFFF); /// @brief Updates the protocol cyclically void update(CANLibBadge) override; @@ -372,7 +372,7 @@ namespace isobus /// @brief A structure to hold data about DM22 responses we need to send struct DM22Data { - ControlFunction *destination; ///< Destination for the DM22 message + std::shared_ptr destination; ///< Destination for the DM22 message std::uint32_t suspectParameterNumber; ///< SPN of the DTC for the DM22 std::uint8_t failureModeIdentifier; ///< FMI of the DTC for the DM22 std::uint8_t nackIndicator; ///< The NACK reason, if applicable @@ -447,8 +447,8 @@ namespace isobus bool protocol_transmit_message(std::uint32_t parameterGroupNumber, const std::uint8_t *data, std::uint32_t messageLength, - ControlFunction *source, - ControlFunction *destination, + std::shared_ptr source, + std::shared_ptr destination, TransmitCompleteCallback transmitCompleteCallback, void *parentPointer, DataChunkCallback frameChunkCallback) override; @@ -472,7 +472,7 @@ namespace isobus /// @brief Sends the DM13 to alert network devices of impending suspended broadcasts /// @returns `true` if the message was sent, otherwise `false` - bool send_dm13_announce_suspension(InternalControlFunction *sourceControlFunction, std::uint16_t suspendTime_seconds); + bool send_dm13_announce_suspension(std::shared_ptr sourceControlFunction, std::uint16_t suspendTime_seconds); /// @brief Sends the ECU ID message /// @returns true if the message was sent @@ -507,7 +507,7 @@ namespace isobus /// @param[out] acknowledgementType The type of acknowledgement to send to the requestor /// @returns true if any callback was able to handle the PGN request bool process_parameter_group_number_request(std::uint32_t parameterGroupNumber, - ControlFunction *requestingControlFunction, + std::shared_ptr requestingControlFunction, bool &acknowledge, AcknowledgementType &acknowledgementType); @@ -519,7 +519,7 @@ namespace isobus /// @param[in] parentPointer Generic context variable, usually a pointer to the class that the callback was registed for /// @returns true if any callback was able to handle the PGN request static bool process_parameter_group_number_request(std::uint32_t parameterGroupNumber, - ControlFunction *requestingControlFunction, + std::shared_ptr requestingControlFunction, bool &acknowledge, AcknowledgementType &acknowledgementType, void *parentPointer); diff --git a/isobus/include/isobus/isobus/isobus_functionalities.hpp b/isobus/include/isobus/isobus/isobus_functionalities.hpp index 85784005..dc8aabed 100644 --- a/isobus/include/isobus/isobus/isobus_functionalities.hpp +++ b/isobus/include/isobus/isobus/isobus_functionalities.hpp @@ -452,7 +452,7 @@ namespace isobus /// @param[out] acknowledgeType Tells the PGN request protocol what kind of ACK to use /// @param[in] parentPointer A generic context variable, usually the "this" pointer of the registrant for callbacks static bool pgn_request_handler(std::uint32_t parameterGroupNumber, - ControlFunction *requestingControlFunction, + std::shared_ptr requestingControlFunction, bool &acknowledge, AcknowledgementType &acknowledgeType, void *parentPointer); diff --git a/isobus/include/isobus/isobus/isobus_guidance_interface.hpp b/isobus/include/isobus/isobus/isobus_guidance_interface.hpp index 62d21145..e42ffc98 100644 --- a/isobus/include/isobus/isobus/isobus_guidance_interface.hpp +++ b/isobus/include/isobus/isobus/isobus_guidance_interface.hpp @@ -69,7 +69,7 @@ namespace isobus /// @brief Constructor for a GuidanceSystemCommand /// @param[in] sender The control function that is sending this message - explicit GuidanceSystemCommand(ControlFunction *sender); + explicit GuidanceSystemCommand(std::shared_ptr sender); /// @brief Sets the curvature command status that will be encoded into /// the CAN message. This parameter indicates whether the guidance system is @@ -100,13 +100,8 @@ namespace isobus float get_curvature() const; /// @brief Returns a pointer to the sender of the message. If an ICF is the sender, returns the ICF being used to transmit from. - /// @attention The only way you could get an invalid pointer here is if you register a partner, it sends this message, then you delete the partner and - /// call this function, as that is the only time the stack deletes a control function. That would be abnormal program flow, but at some point - /// the stack will be updated to return a shared or weak pointer instead, but for now please be aware of that limitation. - /// Eventually though the message will time-out normally and you can get a new pointer for - /// the external CF that replaces the deleted partner. /// @returns The control function sending this instance of the guidance system command message - ControlFunction *get_sender_control_function() const; + std::shared_ptr get_sender_control_function() const; /// @brief Sets the timestamp for when the message was received or sent /// @param[in] timestamp The timestamp, in milliseconds, when the message was sent or received @@ -117,7 +112,7 @@ namespace isobus std::uint32_t get_timestamp_ms() const; private: - ControlFunction *const controlFunction; ///< The CF that is sending the message + std::shared_ptr const controlFunction; ///< The CF that is sending the message float commandedCurvature = 0.0f; ///< The commanded curvature in km^-1 (inverse kilometers) std::uint32_t timestamp_ms = 0; ///< A timestamp for when the message was released in milliseconds CurvatureCommandStatus commandedStatus = CurvatureCommandStatus::NotAvailable; ///< The current status for the command @@ -198,7 +193,7 @@ namespace isobus /// @brief Constructor for a GuidanceMachineInfo /// @param[in] sender The control function that is sending this message - explicit GuidanceMachineInfo(ControlFunction *sender); + explicit GuidanceMachineInfo(std::shared_ptr sender); /// @brief Sets the estimated course curvature over ground for the machine. /// @param[in] curvature The curvature in km^-1 (inverse kilometers). Range is -8032 to 8031.75 km-1 @@ -286,13 +281,8 @@ namespace isobus GenericSAEbs02SlotValue get_guidance_system_remote_engage_switch_status() const; /// @brief Returns a pointer to the sender of the message. If an ICF is the sender, returns the ICF being used to transmit from. - /// @attention The only way you could get an invalid pointer here is if you register a partner, it sends this message, then you delete the partner and - /// call this function, as that is the only time the stack deletes a control function. That would be abnormal program flow, but at some point - /// the stack will be updated to return a shared or weak pointer instead, but for now please be aware of that limitation. - /// Eventually though the message will time-out normally and you can get a new pointer for - /// the external CF that replaces the deleted partner. /// @returns The control function sending this instance of the guidance system command message - ControlFunction *get_sender_control_function() const; + std::shared_ptr get_sender_control_function() const; /// @brief Sets the timestamp for when the message was received or sent /// @param[in] timestamp The timestamp, in milliseconds, when the message was sent or received @@ -303,7 +293,7 @@ namespace isobus std::uint32_t get_timestamp_ms() const; private: - ControlFunction *const controlFunction; ///< The CF that is sending the message + std::shared_ptr const controlFunction; ///< The CF that is sending the message float estimatedCurvature = 0.0f; ///< Curvature in km^-1 (inverse kilometers). Range is -8032 to 8031.75 km-1 (SPN 5238) std::uint32_t timestamp_ms = 0; ///< A timestamp for when the message was released in milliseconds MechanicalSystemLockout mechanicalSystemLockoutState = MechanicalSystemLockout::NotAvailable; ///< The reported state of the mechanical system lockout switch (SPN 5243) diff --git a/isobus/include/isobus/isobus/isobus_task_controller_client.hpp b/isobus/include/isobus/isobus/isobus_task_controller_client.hpp index 270b5114..4a0b91e7 100644 --- a/isobus/include/isobus/isobus/isobus_task_controller_client.hpp +++ b/isobus/include/isobus/isobus/isobus_task_controller_client.hpp @@ -394,8 +394,8 @@ namespace isobus /// @brief The callback passed to the network manager's send function to know when a Tx is completed static void process_tx_callback(std::uint32_t parameterGroupNumber, std::uint32_t dataLength, - InternalControlFunction *sourceControlFunction, - ControlFunction *destinationControlFunction, + std::shared_ptr sourceControlFunction, + std::shared_ptr destinationControlFunction, bool successful, void *parentPointer); diff --git a/isobus/include/isobus/isobus/isobus_virtual_terminal_client.hpp b/isobus/include/isobus/isobus/isobus_virtual_terminal_client.hpp index 30c8a185..ca5b1e95 100644 --- a/isobus/include/isobus/isobus/isobus_virtual_terminal_client.hpp +++ b/isobus/include/isobus/isobus/isobus_virtual_terminal_client.hpp @@ -1487,8 +1487,8 @@ namespace isobus /// @brief The callback passed to the network manager's send function to know when a Tx is completed static void process_callback(std::uint32_t parameterGroupNumber, std::uint32_t dataLength, - InternalControlFunction *sourceControlFunction, - ControlFunction *destinationControlFunction, + std::shared_ptr sourceControlFunction, + std::shared_ptr destinationControlFunction, bool successful, void *parentPointer); diff --git a/isobus/include/isobus/isobus/nmea2000_fast_packet_protocol.hpp b/isobus/include/isobus/isobus/nmea2000_fast_packet_protocol.hpp index e0c92e87..9cb788c1 100644 --- a/isobus/include/isobus/isobus/nmea2000_fast_packet_protocol.hpp +++ b/isobus/include/isobus/isobus/nmea2000_fast_packet_protocol.hpp @@ -48,14 +48,14 @@ namespace isobus /// @param[in] parent Generic context variable /// @param[in] internalControlFunction An internal control function to use as an additional filter for the callback. /// Only messages destined for the specified ICF will generate a callback. Use nullptr to receive all messages. - void register_multipacket_message_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, InternalControlFunction *internalControlFunction = nullptr); + void register_multipacket_message_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, std::shared_ptr internalControlFunction = nullptr); // @brief Removes a callback previously added with register_multipacket_message_callback /// @param[in] parameterGroupNumber The PGN to parse as fast packet /// @param[in] callback The callback that the stack will call when a matching message is received /// @param[in] parent Generic context variable /// @param[in] internalControlFunction An internal control function to use as an additional filter for the callback - void remove_multipacket_message_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, InternalControlFunction *internalControlFunction = nullptr); + void remove_multipacket_message_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, std::shared_ptr internalControlFunction = nullptr); /// @brief Used to send CAN messages using fast packet /// @details You have to use this function instead of the network manager @@ -74,8 +74,8 @@ namespace isobus bool send_multipacket_message(std::uint32_t parameterGroupNumber, const std::uint8_t *data, std::uint8_t messageLength, - InternalControlFunction *source, - ControlFunction *destination, + std::shared_ptr source, + std::shared_ptr destination, CANIdentifier::CANPriority priority = CANIdentifier::CANPriority::PriorityDefault6, TransmitCompleteCallback txCompleteCallback = nullptr, void *parentPointer = nullptr, @@ -155,7 +155,7 @@ namespace isobus /// @param[in] source The session source control function /// @param[in] destination The sesssion destination control function /// @returns `true` if a session was found that matches, otherwise `false` - bool get_session(FastPacketProtocolSession *&returnedSession, std::uint32_t parameterGroupNumber, ControlFunction *source, ControlFunction *destination); + bool get_session(FastPacketProtocolSession *&returnedSession, std::uint32_t parameterGroupNumber, std::shared_ptr source, std::shared_ptr destination); /// @brief A generic way for a protocol to process a received message /// @param[in] message A received CAN message @@ -184,8 +184,8 @@ namespace isobus bool protocol_transmit_message(std::uint32_t parameterGroupNumber, const std::uint8_t *data, std::uint32_t messageLength, - ControlFunction *source, - ControlFunction *destination, + std::shared_ptr source, + std::shared_ptr destination, TransmitCompleteCallback transmitCompleteCallback, void *parentPointer, DataChunkCallback frameChunkCallback) override; diff --git a/isobus/src/can_address_claim_state_machine.cpp b/isobus/src/can_address_claim_state_machine.cpp index 7853c217..93dc663d 100644 --- a/isobus/src/can_address_claim_state_machine.cpp +++ b/isobus/src/can_address_claim_state_machine.cpp @@ -54,7 +54,7 @@ namespace isobus } else { - ControlFunction *deviceAtOurPreferredAddress = CANNetworkManager::CANNetwork.get_control_function(m_portIndex, commandedAddress, {}); + std::shared_ptr deviceAtOurPreferredAddress = CANNetworkManager::CANNetwork.get_control_function(m_portIndex, commandedAddress, {}); m_preferredAddress = commandedAddress; if (nullptr == deviceAtOurPreferredAddress) @@ -132,7 +132,7 @@ namespace isobus if (SystemTiming::time_expired_ms(m_timestamp_ms, addressContentionTime_ms + m_randomClaimDelay_ms)) { - ControlFunction *deviceAtOurPreferredAddress = CANNetworkManager::CANNetwork.get_control_function(m_portIndex, m_preferredAddress, {}); + std::shared_ptr deviceAtOurPreferredAddress = CANNetworkManager::CANNetwork.get_control_function(m_portIndex, m_preferredAddress, {}); // Time to find a free address if (nullptr == deviceAtOurPreferredAddress) { diff --git a/isobus/src/can_callbacks.cpp b/isobus/src/can_callbacks.cpp index fb1c0f8a..cb590e74 100644 --- a/isobus/src/can_callbacks.cpp +++ b/isobus/src/can_callbacks.cpp @@ -10,7 +10,7 @@ namespace isobus { - ParameterGroupNumberCallbackData::ParameterGroupNumberCallbackData(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parentPointer, InternalControlFunction *internalControlFunction) : + ParameterGroupNumberCallbackData::ParameterGroupNumberCallbackData(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parentPointer, std::shared_ptr internalControlFunction) : mCallback(callback), mParameterGroupNumber(parameterGroupNumber), mParent(parentPointer), @@ -58,7 +58,7 @@ namespace isobus return mParent; } - InternalControlFunction *ParameterGroupNumberCallbackData::get_internal_control_function() const + std::shared_ptr ParameterGroupNumberCallbackData::get_internal_control_function() const { return mInternalControlFunctionFilter; } diff --git a/isobus/src/can_control_function.cpp b/isobus/src/can_control_function.cpp index 49c93164..05fcb7bd 100644 --- a/isobus/src/can_control_function.cpp +++ b/isobus/src/can_control_function.cpp @@ -3,6 +3,7 @@ /// /// @brief Defines a base class to represent a generic ISOBUS control function. /// @author Adrian Del Grosso +/// @author Daan Steenbergen /// /// @copyright 2022 Adrian Del Grosso //================================================================================================ @@ -10,22 +11,33 @@ #include "isobus/isobus/can_control_function.hpp" #include "isobus/isobus/can_constants.hpp" +#include "isobus/isobus/can_network_manager.hpp" namespace isobus { std::mutex ControlFunction::controlFunctionProcessingMutex; - ControlFunction::ControlFunction(NAME NAMEValue, std::uint8_t addressValue, std::uint8_t CANPort) : + isobus::ControlFunction::ControlFunction(NAME NAMEValue, std::uint8_t addressValue, std::uint8_t CANPort, Type type) : + controlFunctionType(type), controlFunctionNAME(NAMEValue), - controlFunctionType(Type::External), address(addressValue), canPortIndex(CANPort) + { + } + std::shared_ptr ControlFunction::create(NAME NAMEValue, std::uint8_t addressValue, std::uint8_t CANPort) { + // Unfortunately, we can't use `std::make_shared` here because the constructor is private + return std::shared_ptr(new ControlFunction(NAMEValue, addressValue, CANPort)); } - ControlFunction::~ControlFunction() + bool ControlFunction::destroy(std::uint32_t expectedRefCount) { + std::lock_guard lock(controlFunctionProcessingMutex); + + CANNetworkManager::CANNetwork.on_control_function_destroyed(shared_from_this(), {}); + + return shared_from_this().use_count() == expectedRefCount + 1; } std::uint8_t ControlFunction::get_address() const @@ -53,4 +65,19 @@ namespace isobus return controlFunctionType; } + std::string ControlFunction::get_type_string() const + { + switch (controlFunctionType) + { + case Type::Internal: + return "Internal"; + case Type::External: + return "External"; + case Type::Partnered: + return "Partnered"; + default: + return "Unknown"; + } + } + } // namespace isobus diff --git a/isobus/src/can_extended_transport_protocol.cpp b/isobus/src/can_extended_transport_protocol.cpp index 0df424c8..aaf896d7 100644 --- a/isobus/src/can_extended_transport_protocol.cpp +++ b/isobus/src/can_extended_transport_protocol.cpp @@ -110,7 +110,7 @@ namespace isobus (nullptr != message.get_destination_control_function()) && (ControlFunction::Type::Internal == message.get_destination_control_function()->get_type())) { - abort_session(pgn, ConnectionAbortReason::AlreadyInConnectionManagedSessionAndCannotSupportAnother, reinterpret_cast(message.get_destination_control_function()), message.get_source_control_function()); + abort_session(pgn, ConnectionAbortReason::AlreadyInConnectionManagedSessionAndCannotSupportAnother, std::dynamic_pointer_cast(message.get_destination_control_function()), message.get_source_control_function()); CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Error, "[ETP]: Sent abort to address " + isobus::to_string(static_cast(message.get_source_control_function()->get_address())) + " RTS when already in session"); close_session(session, false); } @@ -118,7 +118,7 @@ namespace isobus (nullptr != message.get_destination_control_function()) && (ControlFunction::Type::Internal == message.get_destination_control_function()->get_type())) { - abort_session(pgn, ConnectionAbortReason::SystemResourcesNeededForAnotherTask, reinterpret_cast(message.get_destination_control_function()), message.get_source_control_function()); + abort_session(pgn, ConnectionAbortReason::SystemResourcesNeededForAnotherTask, std::dynamic_pointer_cast(message.get_destination_control_function()), message.get_source_control_function()); CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Error, "[ETP]: Sent abort to address " + isobus::to_string(static_cast(message.get_source_control_function()->get_address())) + " No Sessions Available"); close_session(session, false); } @@ -147,7 +147,7 @@ namespace isobus { // The session exists, but we're probably already in the TxDataSession state. Need to abort // In the case of Rx'ing a CTS, we're the source in the session - abort_session(pgn, ConnectionAbortReason::ClearToSendReceivedWhenDataTransferInProgress, reinterpret_cast(message.get_destination_control_function()), message.get_source_control_function()); + abort_session(pgn, ConnectionAbortReason::ClearToSendReceivedWhenDataTransferInProgress, std::dynamic_pointer_cast(message.get_destination_control_function()), message.get_source_control_function()); CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Error, "[ETP]: Sent abort to address " + isobus::to_string(static_cast(message.get_source_control_function()->get_address())) + " CTS while in data session"); close_session(session, false); } @@ -156,7 +156,7 @@ namespace isobus { // We got a CTS but no session exists. Aborting clears up the situation faster than waiting for them to timeout // In the case of Rx'ing a CTS, we're the source in the session - abort_session(pgn, ConnectionAbortReason::AnyOtherReason, reinterpret_cast(message.get_destination_control_function()), message.get_source_control_function()); + abort_session(pgn, ConnectionAbortReason::AnyOtherReason, std::dynamic_pointer_cast(message.get_destination_control_function()), message.get_source_control_function()); CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Error, "[ETP]: Sent abort to address " + isobus::to_string(static_cast(message.get_source_control_function()->get_address())) + " CTS With no matching session"); } } @@ -221,7 +221,7 @@ namespace isobus if (!anySessionMatched) { - abort_session(pgn, ConnectionAbortReason::UnexpectedEDPOPacket, reinterpret_cast(message.get_destination_control_function()), message.get_source_control_function()); + abort_session(pgn, ConnectionAbortReason::UnexpectedEDPOPacket, std::dynamic_pointer_cast(message.get_destination_control_function()), message.get_source_control_function()); } } } @@ -242,14 +242,14 @@ namespace isobus } else { - abort_session(pgn, ConnectionAbortReason::AnyOtherReason, reinterpret_cast(message.get_destination_control_function()), message.get_source_control_function()); + abort_session(pgn, ConnectionAbortReason::AnyOtherReason, std::dynamic_pointer_cast(message.get_destination_control_function()), message.get_source_control_function()); close_session(session, false); CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Error, "[ETP]: Sent abort to address " + isobus::to_string(static_cast(message.get_source_control_function()->get_address())) + " received EOM in wrong session state"); } } else { - abort_session(pgn, ConnectionAbortReason::AnyOtherReason, reinterpret_cast(message.get_destination_control_function()), message.get_source_control_function()); + abort_session(pgn, ConnectionAbortReason::AnyOtherReason, std::dynamic_pointer_cast(message.get_destination_control_function()), message.get_source_control_function()); CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Error, "[ETP]: Sent abort to address " + isobus::to_string(static_cast(message.get_source_control_function()->get_address())) + " EOM without matching session"); } } @@ -337,8 +337,8 @@ namespace isobus bool ExtendedTransportProtocolManager::protocol_transmit_message(std::uint32_t parameterGroupNumber, const std::uint8_t *dataBuffer, std::uint32_t messageLength, - ControlFunction *source, - ControlFunction *destination, + std::shared_ptr source, + std::shared_ptr destination, TransmitCompleteCallback sessionCompleteCallback, void *parentPointer, DataChunkCallback frameChunkCallback) @@ -408,8 +408,8 @@ namespace isobus if (nullptr != session) { - InternalControlFunction *myControlFunction; - ControlFunction *partnerControlFunction; + std::shared_ptr myControlFunction; + std::shared_ptr partnerControlFunction; std::array data; std::uint32_t pgn = session->sessionMessage.get_identifier().get_parameter_group_number(); @@ -442,7 +442,7 @@ namespace isobus return retVal; } - bool ExtendedTransportProtocolManager::abort_session(std::uint32_t parameterGroupNumber, ConnectionAbortReason reason, InternalControlFunction *source, ControlFunction *destination) + bool ExtendedTransportProtocolManager::abort_session(std::uint32_t parameterGroupNumber, ConnectionAbortReason reason, std::shared_ptr source, std::shared_ptr destination) { std::array data; @@ -477,7 +477,7 @@ namespace isobus } } - bool ExtendedTransportProtocolManager::get_session(ExtendedTransportProtocolSession *&session, ControlFunction *source, ControlFunction *destination) const + bool ExtendedTransportProtocolManager::get_session(ExtendedTransportProtocolSession *&session, std::shared_ptr source, std::shared_ptr destination) const { session = nullptr; @@ -493,7 +493,7 @@ namespace isobus return (nullptr != session); } - bool ExtendedTransportProtocolManager::get_session(ExtendedTransportProtocolSession *&session, ControlFunction *source, ControlFunction *destination, std::uint32_t parameterGroupNumber) const + bool ExtendedTransportProtocolManager::get_session(ExtendedTransportProtocolSession *&session, std::shared_ptr source, std::shared_ptr destination, std::uint32_t parameterGroupNumber) const { bool retVal = false; session = nullptr; @@ -515,7 +515,7 @@ namespace isobus { session->sessionCompleteCallback(session->sessionMessage.get_identifier().get_parameter_group_number(), session->get_message_data_length(), - reinterpret_cast(session->sessionMessage.get_source_control_function()), + std::dynamic_pointer_cast(session->sessionMessage.get_source_control_function()), session->sessionMessage.get_destination_control_function(), success, session->parent); @@ -540,7 +540,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ExtendedTransportProtocolConnectionManagement), dataBuffer, CAN_DATA_LENGTH, - reinterpret_cast(session->sessionMessage.get_destination_control_function()), + std::dynamic_pointer_cast(session->sessionMessage.get_destination_control_function()), session->sessionMessage.get_source_control_function(), CANIdentifier::CANPriority::PriorityDefault6); } @@ -576,7 +576,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ExtendedTransportProtocolConnectionManagement), dataBuffer, CAN_DATA_LENGTH, - reinterpret_cast(session->sessionMessage.get_destination_control_function()), + std::dynamic_pointer_cast(session->sessionMessage.get_destination_control_function()), session->sessionMessage.get_source_control_function(), CANIdentifier::CANPriority::PriorityDefault6); } @@ -600,7 +600,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ExtendedTransportProtocolConnectionManagement), dataBuffer, CAN_DATA_LENGTH, - reinterpret_cast(session->sessionMessage.get_source_control_function()), + std::dynamic_pointer_cast(session->sessionMessage.get_source_control_function()), session->sessionMessage.get_destination_control_function(), CANIdentifier::CANPriority::PriorityDefault6); } @@ -624,7 +624,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ExtendedTransportProtocolConnectionManagement), dataBuffer, CAN_DATA_LENGTH, - reinterpret_cast(session->sessionMessage.get_source_control_function()), + std::dynamic_pointer_cast(session->sessionMessage.get_source_control_function()), session->sessionMessage.get_destination_control_function(), CANIdentifier::CANPriority::PriorityDefault6); } @@ -754,7 +754,7 @@ namespace isobus if (CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ExtendedTransportProtocolDataTransfer), dataBuffer, CAN_DATA_LENGTH, - reinterpret_cast(session->sessionMessage.get_source_control_function()), + std::dynamic_pointer_cast(session->sessionMessage.get_source_control_function()), session->sessionMessage.get_destination_control_function(), CANIdentifier::CANPriority::PriorityLowest7)) { diff --git a/isobus/src/can_internal_control_function.cpp b/isobus/src/can_internal_control_function.cpp index e38f67ff..5c9b8b50 100644 --- a/isobus/src/can_internal_control_function.cpp +++ b/isobus/src/can_internal_control_function.cpp @@ -4,6 +4,7 @@ /// @brief A representation of an ISOBUS ECU that we can send from. Use this class /// when defining your own control functions that will claim an address within your program. /// @author Adrian Del Grosso +/// @author Daan Steenbergen /// /// @copyright 2022 Adrian Del Grosso //================================================================================================ @@ -15,45 +16,36 @@ namespace isobus { - std::vector InternalControlFunction::internalControlFunctionList; + std::vector> InternalControlFunction::internalControlFunctionList; bool InternalControlFunction::anyChangedAddress = false; InternalControlFunction::InternalControlFunction(NAME desiredName, std::uint8_t preferredAddress, std::uint8_t CANPort) : - ControlFunction(desiredName, NULL_CAN_ADDRESS, CANPort), + ControlFunction(desiredName, NULL_CAN_ADDRESS, CANPort, Type::Internal), stateMachine(preferredAddress, desiredName, CANPort), objectChangedAddressSinceLastUpdate(false) { - const std::lock_guard lock(ControlFunction::controlFunctionProcessingMutex); - controlFunctionType = Type::Internal; + } - auto location = std::find(internalControlFunctionList.begin(), internalControlFunctionList.end(), nullptr); - if (internalControlFunctionList.end() != location) - { - *location = this; // Use the available space in the list - } - else - { - internalControlFunctionList.push_back(this); // Allocate space in the list for this ICF - } + std::shared_ptr InternalControlFunction::create(NAME desiredName, std::uint8_t preferredAddress, std::uint8_t CANPort) + { + // Unfortunately, we can't use `std::make_shared` here because the constructor is private + auto createdControlFunction = std::shared_ptr(new InternalControlFunction(desiredName, preferredAddress, CANPort)); + internalControlFunctionList.push_back(createdControlFunction); + return createdControlFunction; } - InternalControlFunction::~InternalControlFunction() + bool InternalControlFunction::destroy(std::uint32_t expectedRefCount) { - const std::lock_guard lock(ControlFunction::controlFunctionProcessingMutex); - if (!internalControlFunctionList.empty()) - { - auto thisObject = std::find(internalControlFunctionList.begin(), internalControlFunctionList.end(), this); + std::unique_lock lock(controlFunctionProcessingMutex); + internalControlFunctionList.erase(std::find(internalControlFunctionList.begin(), internalControlFunctionList.end(), shared_from_this())); + lock.unlock(); - if (internalControlFunctionList.end() != thisObject) - { - *thisObject = nullptr; // Don't erase, just null it out. Erase could cause a double free. - } - } + return ControlFunction::destroy(expectedRefCount); } - InternalControlFunction *InternalControlFunction::get_internal_control_function(std::uint32_t index) + std::shared_ptr InternalControlFunction::get_internal_control_function(std::uint32_t index) { - InternalControlFunction *retVal = nullptr; + std::shared_ptr retVal = nullptr; if (index < get_number_internal_control_functions()) { diff --git a/isobus/src/can_message.cpp b/isobus/src/can_message.cpp index 028900d2..2c057d41 100644 --- a/isobus/src/can_message.cpp +++ b/isobus/src/can_message.cpp @@ -34,12 +34,12 @@ namespace isobus return data.size(); } - ControlFunction *CANMessage::get_source_control_function() const + std::shared_ptr CANMessage::get_source_control_function() const { return source; } - ControlFunction *CANMessage::get_destination_control_function() const + std::shared_ptr CANMessage::get_destination_control_function() const { return destination; } @@ -74,12 +74,12 @@ namespace isobus data.resize(length); } - void CANMessage::set_source_control_function(ControlFunction *value) + void CANMessage::set_source_control_function(std::shared_ptr value) { source = value; } - void CANMessage::set_destination_control_function(ControlFunction *value) + void CANMessage::set_destination_control_function(std::shared_ptr value) { destination = value; } diff --git a/isobus/src/can_network_manager.cpp b/isobus/src/can_network_manager.cpp index 2e39c4a8..d8ee9f6f 100644 --- a/isobus/src/can_network_manager.cpp +++ b/isobus/src/can_network_manager.cpp @@ -4,6 +4,7 @@ /// @brief The main class that manages the ISOBUS stack including: callbacks, Name to Address /// management, making control functions, and driving the various protocols. /// @author Adrian Del Grosso +/// @author Daan Steenbergen /// /// @copyright 2022 Adrian Del Grosso //================================================================================================ @@ -35,16 +36,16 @@ namespace isobus extendedTransportProtocol.initialize({}); } - ControlFunction *CANNetworkManager::get_control_function(std::uint8_t CANPort, std::uint8_t CFAddress, CANLibBadge) const + std::shared_ptr CANNetworkManager::get_control_function(std::uint8_t channelIndex, std::uint8_t address, CANLibBadge) const { - return get_control_function(CANPort, CFAddress); + return get_control_function(channelIndex, address); } - void CANNetworkManager::add_control_function(std::uint8_t CANPort, ControlFunction *newControlFunction, std::uint8_t CFAddress, CANLibBadge) + void CANNetworkManager::add_control_function(std::uint8_t channelIndex, std::shared_ptr newControlFunction, std::uint8_t address, CANLibBadge) { - if ((nullptr != newControlFunction) && (CFAddress < NULL_CAN_ADDRESS) && (CANPort < CAN_PORT_MAXIMUM)) + if ((nullptr != newControlFunction) && (address < NULL_CAN_ADDRESS) && (channelIndex < CAN_PORT_MAXIMUM)) { - controlFunctionTable[CANPort][CFAddress] = newControlFunction; + controlFunctionTable[channelIndex][address] = newControlFunction; } } @@ -85,14 +86,14 @@ namespace isobus } } - InternalControlFunction *CANNetworkManager::get_internal_control_function(ControlFunction *controlFunction) + std::shared_ptr CANNetworkManager::get_internal_control_function(std::shared_ptr controlFunction) { - InternalControlFunction *retVal = nullptr; + std::shared_ptr retVal = nullptr; if ((nullptr != controlFunction) && (ControlFunction::Type::Internal == controlFunction->get_type())) { - retVal = static_cast(controlFunction); + retVal = std::static_pointer_cast(controlFunction); } return retVal; } @@ -115,8 +116,8 @@ namespace isobus bool CANNetworkManager::send_can_message(std::uint32_t parameterGroupNumber, const std::uint8_t *dataBuffer, std::uint32_t dataLength, - InternalControlFunction *sourceControlFunction, - ControlFunction *destinationControlFunction, + std::shared_ptr sourceControlFunction, + std::shared_ptr destinationControlFunction, CANIdentifier::CANPriority priority, TransmitCompleteCallback transmitCompleteCallback, void *parentPointer, @@ -209,13 +210,15 @@ namespace isobus { for (std::size_t i = 0; i < InternalControlFunction::get_number_internal_control_functions(); i++) { - InternalControlFunction *currentInternalControlFunction = InternalControlFunction::get_internal_control_function(i); + std::shared_ptr currentInternalControlFunction = InternalControlFunction::get_internal_control_function(i); if (nullptr != currentInternalControlFunction) { - if (activeControlFunctions.end() == std::find(activeControlFunctions.begin(), activeControlFunctions.end(), currentInternalControlFunction)) + if (inactiveControlFunctions.end() == std::find_if(inactiveControlFunctions.begin(), inactiveControlFunctions.end(), [currentInternalControlFunction](const std::shared_ptr &cf_ptr) { + return (cf_ptr == currentInternalControlFunction); + })) { - activeControlFunctions.push_back(currentInternalControlFunction); + inactiveControlFunctions.push_back(std::shared_ptr(currentInternalControlFunction)); } if (currentInternalControlFunction->get_changed_address_since_last_update({})) { @@ -288,28 +291,8 @@ namespace isobus tempCANMessage.set_identifier(CANIdentifier(rxFrame.identifier)); - // Note, if this is an address claim message, the address to CF table might be stale. - // We don't want to update that here though, as we're maybe in some other thread in this callback. - // So for now, manually search all of them to line up the appropriate CF. A bit unfortunate in that we may have a lot of CFs, but saves pain later so we don't have to - // do some gross cast to CANMessage to edit the CFs. - // At least address claiming should be infrequent, so this should not happen a ton. - if (static_cast(CANLibParameterGroupNumber::AddressClaim) == tempCANMessage.get_identifier().get_parameter_group_number()) - { - for (std::uint32_t i = 0; i < CANNetworkManager::CANNetwork.activeControlFunctions.size(); i++) - { - if ((CANNetworkManager::CANNetwork.activeControlFunctions[i]->get_can_port() == tempCANMessage.get_can_port_index()) && - (CANNetworkManager::CANNetwork.activeControlFunctions[i]->get_address() == tempCANMessage.get_identifier().get_source_address())) - { - tempCANMessage.set_source_control_function(CANNetworkManager::CANNetwork.activeControlFunctions[i]); - break; - } - } - } - else - { - tempCANMessage.set_source_control_function(CANNetworkManager::CANNetwork.get_control_function(rxFrame.channel, tempCANMessage.get_identifier().get_source_address())); - tempCANMessage.set_destination_control_function(CANNetworkManager::CANNetwork.get_control_function(rxFrame.channel, tempCANMessage.get_identifier().get_destination_address())); - } + tempCANMessage.set_source_control_function(CANNetworkManager::CANNetwork.get_control_function(rxFrame.channel, tempCANMessage.get_identifier().get_source_address())); + tempCANMessage.set_destination_control_function(CANNetworkManager::CANNetwork.get_control_function(rxFrame.channel, tempCANMessage.get_identifier().get_destination_address())); tempCANMessage.set_data(rxFrame.data, rxFrame.dataLength); CANNetworkManager::CANNetwork.update_busload(rxFrame.channel, rxFrame.get_number_bits_in_message()); @@ -322,37 +305,41 @@ namespace isobus CANNetworkManager::CANNetwork.update_busload(txFrame.channel, txFrame.get_number_bits_in_message()); } - void CANNetworkManager::on_partner_deleted(PartneredControlFunction *partner, CANLibBadge) + void CANNetworkManager::on_control_function_destroyed(std::shared_ptr controlFunction, CANLibBadge) { - CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Debug, "[NM]: Partner " + isobus::to_string(static_cast(partner->get_address())) + " was deleted."); + auto result = std::find(inactiveControlFunctions.begin(), inactiveControlFunctions.end(), controlFunction); + if (result != inactiveControlFunctions.end()) + { + inactiveControlFunctions.erase(result); + } - for (auto activeControlFunction = activeControlFunctions.begin(); activeControlFunction != activeControlFunctions.end(); activeControlFunction++) + for (std::uint8_t i = 0; i < NULL_CAN_ADDRESS; i++) { - if ((partner->get_can_port() == (*activeControlFunction)->get_can_port()) && - (partner->get_NAME() == (*activeControlFunction)->get_NAME())) + if (controlFunctionTable[controlFunction->get_can_port()][i] == controlFunction) { - (*activeControlFunction) = nullptr; - activeControlFunctions.erase(activeControlFunction); - if (partner->address < NULL_CAN_ADDRESS) + if (i != controlFunction->get_address()) { - controlFunctionTable[partner->get_can_port()][partner->address] = nullptr; - // If the control function was active, replace it with an external control function - activeControlFunctions.push_back(new ControlFunction(partner->get_NAME(), partner->get_address(), partner->get_can_port())); - CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Debug, "[NM]: Since the deleted partner was active, it has been replaced with an external control function."); + CANStackLogger::warn("[NM]: %s control function with address '%d' was at address '%d' in the lookup table prior to deletion.", controlFunction->get_type_string().c_str(), controlFunction->get_address(), i); + } + + if (initialized) + { + // The control function was active, replace it with an new external control function + controlFunctionTable[controlFunction->get_can_port()][controlFunction->address] = ControlFunction::create(controlFunction->get_NAME(), controlFunction->get_address(), controlFunction->get_can_port()); + } + else + { + // The network manager is not initialized yet, just remove the control function from the table + controlFunctionTable[controlFunction->get_can_port()][i] = nullptr; } - break; - } - } - for (auto inactiveControlFunction = inactiveControlFunctions.begin(); inactiveControlFunction != inactiveControlFunctions.end(); inactiveControlFunction++) - { - if ((partner->get_can_port() == (*inactiveControlFunction)->get_can_port()) && - (partner->get_NAME() == (*inactiveControlFunction)->get_NAME())) - { - (*inactiveControlFunction) = nullptr; - inactiveControlFunctions.erase(inactiveControlFunction); - break; } } + CANStackLogger::debug("[NM]: %s control function with address '%d' is deleted.", controlFunction->get_type_string().c_str(), controlFunction->get_address()); + } + + void CANNetworkManager::on_control_function_created(std::shared_ptr controlFunction, CANLibBadge) + { + //! @todo implement this when we stop using the dedicated internal/partner control functions lists in their respective classes } FastPacketProtocol &CANNetworkManager::get_fast_packet_protocol() @@ -411,57 +398,62 @@ namespace isobus { std::uint8_t messageSourceAddress = message.get_identifier().get_source_address(); - if ((nullptr != controlFunctionTable[CANPort][messageSourceAddress]) && - (CANIdentifier::NULL_ADDRESS == controlFunctionTable[CANPort][messageSourceAddress]->get_address())) + update_address_table(CANPort, messageSourceAddress); + } + } + + void CANNetworkManager::update_address_table(std::uint8_t channelIndex, std::uint8_t claimedAddress) + { + if (channelIndex < CAN_PORT_MAXIMUM) + { + if ((nullptr != controlFunctionTable[channelIndex][claimedAddress]) && + (CANIdentifier::NULL_ADDRESS == controlFunctionTable[channelIndex][claimedAddress]->get_address())) { // Someone is at that spot in the table, but their address was stolen - // Need to evict them from the table - controlFunctionTable[CANPort][messageSourceAddress]->address = NULL_CAN_ADDRESS; - controlFunctionTable[CANPort][messageSourceAddress] = nullptr; + // Need to evict them from the table and move them to the inactive list + controlFunctionTable[channelIndex][claimedAddress]->address = NULL_CAN_ADDRESS; + inactiveControlFunctions.push_back(controlFunctionTable[channelIndex][claimedAddress]); + controlFunctionTable[channelIndex][claimedAddress] = nullptr; + CANStackLogger::debug("[NM]: %s CF '%d' was evicted from address '%d' on channel '%d' in the lookup table.", + controlFunctionTable[channelIndex][claimedAddress]->get_type_string().c_str(), + controlFunctionTable[channelIndex][claimedAddress]->get_NAME().get_full_name(), + claimedAddress, + channelIndex); } // Now, check for either a free spot in the table or recent eviction and populate if needed - if (nullptr == controlFunctionTable[CANPort][messageSourceAddress]) + if (nullptr == controlFunctionTable[channelIndex][claimedAddress]) { - // Look through active CFs, maybe we've heard of this ECU before - for (auto currentControlFunction : activeControlFunctions) + // Look through all active CFs, maybe one of them has switched addresses + for (std::uint8_t i = 0; i < NULL_CAN_ADDRESS; i++) { - if (currentControlFunction->get_address() == messageSourceAddress) + if ((nullptr != controlFunctionTable[channelIndex][i]) && + (i != claimedAddress) && + (controlFunctionTable[channelIndex][i]->get_address() == claimedAddress)) { - // ECU has claimed since the last update, add it to the table - controlFunctionTable[CANPort][messageSourceAddress] = currentControlFunction; - currentControlFunction->address = messageSourceAddress; + controlFunctionTable[channelIndex][claimedAddress] = controlFunctionTable[channelIndex][i]; + controlFunctionTable[channelIndex][i] = nullptr; + CANStackLogger::debug("[NM]: %s CF '%d' moved from address '%d' to address '%d' on channel '%d' in the lookup table.", + controlFunctionTable[channelIndex][claimedAddress]->get_type_string().c_str(), + controlFunctionTable[channelIndex][claimedAddress]->get_NAME().get_full_name(), + i, + claimedAddress, + channelIndex); break; } } - } - } - } - void CANNetworkManager::update_address_table(std::uint8_t CANPort, std::uint8_t claimedAddress) - { - if (CANPort < CAN_PORT_MAXIMUM) - { - if ((nullptr != controlFunctionTable[CANPort][claimedAddress]) && - (CANIdentifier::NULL_ADDRESS == controlFunctionTable[CANPort][claimedAddress]->get_address())) - { - // Someone is at that spot in the table, but their address was stolen - // Need to evict them from the table - controlFunctionTable[CANPort][claimedAddress]->address = NULL_CAN_ADDRESS; - controlFunctionTable[CANPort][claimedAddress] = nullptr; - } - - // Now, check for either a free spot in the table or recent eviction and populate if needed - if (nullptr == controlFunctionTable[CANPort][claimedAddress]) - { - // Look through active CFs, maybe we've heard of this ECU before - for (auto currentControlFunction : activeControlFunctions) + // Look through all inactive CFs, maybe one of them has freshly claimed an address + for (auto currentControlFunction : inactiveControlFunctions) { if (currentControlFunction->get_address() == claimedAddress) { - // ECU has claimed since the last update, add it to the table - controlFunctionTable[CANPort][claimedAddress] = currentControlFunction; - currentControlFunction->address = claimedAddress; + controlFunctionTable[channelIndex][claimedAddress] = currentControlFunction; + CANStackLogger::debug("[NM]: %s CF '%d' moved from inactive to address '%d' on channel '%d' in the lookup table.", + currentControlFunction->get_type_string().c_str(), + currentControlFunction->get_NAME().get_full_name(), + claimedAddress, + channelIndex); break; } } @@ -503,7 +495,7 @@ namespace isobus (rxFrame.channel < CAN_PORT_MAXIMUM)) { std::uint64_t claimedNAME; - ControlFunction *foundControlFunction = nullptr; + std::shared_ptr foundControlFunction = nullptr; claimedNAME = rxFrame.data[0]; claimedNAME |= (static_cast(rxFrame.data[1]) << 8); @@ -514,38 +506,26 @@ namespace isobus claimedNAME |= (static_cast(rxFrame.data[6]) << 48); claimedNAME |= (static_cast(rxFrame.data[7]) << 56); - for (std::size_t i = 0; i < activeControlFunctions.size(); i++) + // Check if the claimed NAME is someone we already know about + auto activeResult = std::find_if(controlFunctionTable[rxFrame.channel].begin(), + controlFunctionTable[rxFrame.channel].end(), + [claimedNAME](const std::shared_ptr &cf) { + return (nullptr != cf) && (cf->controlFunctionNAME.get_full_name() == claimedNAME); + }); + if (activeResult != controlFunctionTable[rxFrame.channel].end()) { - if ((claimedNAME == activeControlFunctions[i]->controlFunctionNAME.get_full_name()) && - (rxFrame.channel == activeControlFunctions[i]->get_can_port())) - { - // Device already in the active list - foundControlFunction = activeControlFunctions[i]; - break; - } - else if ((activeControlFunctions[i]->address == CANIdentifier(rxFrame.identifier).get_source_address()) && - (rxFrame.channel == activeControlFunctions[i]->get_can_port())) - { - // If this CF has the same address as the one claiming, we need set it to 0xFE (null address) - activeControlFunctions[i]->address = CANIdentifier::NULL_ADDRESS; - } + foundControlFunction = *activeResult; } - - // Maybe it's in the inactive list (device reconnected) - // Always have to iterate the list to check for duplicate addresses - for (std::size_t i = 0; i < inactiveControlFunctions.size(); i++) + else { - if ((claimedNAME == inactiveControlFunctions[i]->controlFunctionNAME.get_full_name()) && - (rxFrame.channel == inactiveControlFunctions[i]->get_can_port())) - { - // Device already in the inactive list - foundControlFunction = inactiveControlFunctions[i]; - break; - } - else if (rxFrame.channel == inactiveControlFunctions[i]->get_can_port()) + auto inActiveResult = std::find_if(inactiveControlFunctions.begin(), + inactiveControlFunctions.end(), + [claimedNAME, &rxFrame](const std::shared_ptr &cf) { + return (cf->controlFunctionNAME.get_full_name() == claimedNAME) && (cf->get_can_port() == rxFrame.channel); + }); + if (inActiveResult != inactiveControlFunctions.end()) { - // If this CF has the same address as the one claiming, we need set it to 0xFE (null address) - inactiveControlFunctions[i]->address = CANIdentifier::NULL_ADDRESS; + foundControlFunction = *inActiveResult; } } @@ -560,19 +540,40 @@ namespace isobus { PartneredControlFunction::partneredControlFunctionList[i]->address = CANIdentifier(rxFrame.identifier).get_source_address(); PartneredControlFunction::partneredControlFunctionList[i]->controlFunctionNAME = NAME(claimedNAME); - activeControlFunctions.push_back(PartneredControlFunction::partneredControlFunctionList[i]); - foundControlFunction = PartneredControlFunction::partneredControlFunctionList[i]; - CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Debug, "[NM]: A Partner Has Claimed " + isobus::to_string(static_cast(CANIdentifier(rxFrame.identifier).get_source_address()))); + foundControlFunction = std::shared_ptr(PartneredControlFunction::partneredControlFunctionList[i]); + controlFunctionTable[rxFrame.channel][foundControlFunction->get_address()] = foundControlFunction; break; } } + } - if (nullptr == foundControlFunction) - { - // New device, need to start keeping track of it - activeControlFunctions.push_back(new ControlFunction(NAME(claimedNAME), CANIdentifier(rxFrame.identifier).get_source_address(), rxFrame.channel)); - CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Debug, "[NM]: New Control function " + isobus::to_string(static_cast(CANIdentifier(rxFrame.identifier).get_source_address()))); - } + // Remove any CF that has the same address as the one claiming + std::for_each(controlFunctionTable[rxFrame.channel].begin(), + controlFunctionTable[rxFrame.channel].end(), + [&rxFrame, &foundControlFunction](const std::shared_ptr &cf) { + if ((nullptr != cf) && (foundControlFunction != cf) && (cf->address == CANIdentifier(rxFrame.identifier).get_source_address())) + cf->address = CANIdentifier::NULL_ADDRESS; + }); + + std::for_each(inactiveControlFunctions.begin(), + inactiveControlFunctions.end(), + [&rxFrame, &foundControlFunction](const std::shared_ptr &cf) { + if ((foundControlFunction != cf) && (cf->address == CANIdentifier(rxFrame.identifier).get_source_address()) && (cf->get_can_port() == rxFrame.channel)) + cf->address = CANIdentifier::NULL_ADDRESS; + }); + + if (nullptr == foundControlFunction) + { + // New device, need to start keeping track of it + foundControlFunction = ControlFunction::create(NAME(claimedNAME), CANIdentifier(rxFrame.identifier).get_source_address(), rxFrame.channel); + controlFunctionTable[rxFrame.channel][foundControlFunction->get_address()] = foundControlFunction; + CANStackLogger::debug("[NM]: New Control function %d", foundControlFunction->get_address()); + } + else + { + CANStackLogger::debug("[NM]: A %s control function (re-)claimed '%d'.", + foundControlFunction->get_type_string().c_str(), + foundControlFunction->get_address()); } if (nullptr != foundControlFunction) @@ -615,12 +616,15 @@ namespace isobus if (!foundReplaceableControlFunction) { - for (auto currentActiveControlFunction = activeControlFunctions.begin(); currentActiveControlFunction != activeControlFunctions.end(); currentActiveControlFunction++) + for (auto currentActiveControlFunction = controlFunctionTable[partner->get_can_port()].begin(); currentActiveControlFunction != controlFunctionTable[partner->get_can_port()].end(); currentActiveControlFunction++) { - if ((partner->check_matches_name((*currentActiveControlFunction)->get_NAME())) && + if ((nullptr != (*currentActiveControlFunction)) && + (partner->check_matches_name((*currentActiveControlFunction)->get_NAME())) && (partner->get_can_port() == (*currentActiveControlFunction)->get_can_port()) && (ControlFunction::Type::External == (*currentActiveControlFunction)->get_type())) { + foundReplaceableControlFunction = true; + // This CF matches the filter and is not an internal or already partnered CF CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Debug, "[NM]: Remapping new partner control function to an active external control function at address " + isobus::to_string(static_cast((*currentActiveControlFunction)->get_address()))); @@ -628,9 +632,7 @@ namespace isobus partner->address = (*currentActiveControlFunction)->get_address(); partner->controlFunctionNAME = (*currentActiveControlFunction)->get_NAME(); partner->initialized = true; - controlFunctionTable[partner->get_can_port()][partner->address] = partner; - activeControlFunctions.erase(currentActiveControlFunction); - activeControlFunctions.push_back(partner); + controlFunctionTable[partner->get_can_port()][partner->address] = std::shared_ptr(partner); break; } } @@ -702,13 +704,13 @@ namespace isobus return txFrame; } - ControlFunction *CANNetworkManager::get_control_function(std::uint8_t CANPort, std::uint8_t CFAddress) const + std::shared_ptr CANNetworkManager::get_control_function(std::uint8_t channelIndex, std::uint8_t address) const { - ControlFunction *retVal = nullptr; + std::shared_ptr retVal = nullptr; - if ((CFAddress < NULL_CAN_ADDRESS) && (CANPort < CAN_PORT_MAXIMUM)) + if ((address < NULL_CAN_ADDRESS) && (channelIndex < CAN_PORT_MAXIMUM)) { - retVal = controlFunctionTable[CANPort][CFAddress]; + retVal = controlFunctionTable[channelIndex][address]; } return retVal; } @@ -755,7 +757,7 @@ namespace isobus void CANNetworkManager::process_can_message_for_global_and_partner_callbacks(const CANMessage &message) { - ControlFunction *messageDestination = message.get_destination_control_function(); + std::shared_ptr messageDestination = message.get_destination_control_function(); if ((nullptr == messageDestination) && ((nullptr != message.get_source_control_function()) || ((static_cast(CANLibParameterGroupNumber::ParameterGroupNumberRequest) == message.get_identifier().get_parameter_group_number()) && @@ -782,7 +784,7 @@ namespace isobus // Message is destined to us for (std::size_t j = 0; j < PartneredControlFunction::get_number_partnered_control_functions(); j++) { - PartneredControlFunction *currentControlFunction = PartneredControlFunction::get_partnered_control_function(j); + std::shared_ptr currentControlFunction = PartneredControlFunction::get_partnered_control_function(j); if ((nullptr != currentControlFunction) && (currentControlFunction->get_can_port() == message.get_can_port_index())) diff --git a/isobus/src/can_parameter_group_number_request_protocol.cpp b/isobus/src/can_parameter_group_number_request_protocol.cpp index 7c7ddbfc..3038bfef 100644 --- a/isobus/src/can_parameter_group_number_request_protocol.cpp +++ b/isobus/src/can_parameter_group_number_request_protocol.cpp @@ -81,7 +81,7 @@ namespace isobus return retVal; } - bool ParameterGroupNumberRequestProtocol::request_parameter_group_number(std::uint32_t pgn, InternalControlFunction *source, ControlFunction *destination) + bool ParameterGroupNumberRequestProtocol::request_parameter_group_number(std::uint32_t pgn, std::shared_ptr source, std::shared_ptr destination) { std::array buffer; @@ -96,7 +96,7 @@ namespace isobus destination); } - bool ParameterGroupNumberRequestProtocol::request_repetition_rate(std::uint32_t pgn, std::uint16_t repetitionRate_ms, InternalControlFunction *source, ControlFunction *destination) + bool ParameterGroupNumberRequestProtocol::request_repetition_rate(std::uint32_t pgn, std::uint16_t repetitionRate_ms, std::shared_ptr source, std::shared_ptr destination) { std::array buffer; @@ -218,7 +218,7 @@ namespace isobus { if ((((nullptr == message.get_destination_control_function()) && (BROADCAST_CAN_ADDRESS == message.get_identifier().get_destination_address())) || - (message.get_destination_control_function() == myControlFunction.get()))) + (message.get_destination_control_function() == myControlFunction))) { switch (message.get_identifier().get_parameter_group_number()) { @@ -289,7 +289,7 @@ namespace isobus { send_acknowledgement(ackType, requestedPGN, - reinterpret_cast(message.get_destination_control_function()), + std::dynamic_pointer_cast(message.get_destination_control_function()), message.get_source_control_function()); } // If this callback was able to process the PGN request, stop processing more. @@ -301,7 +301,7 @@ namespace isobus { send_acknowledgement(AcknowledgementType::Negative, requestedPGN, - reinterpret_cast(message.get_destination_control_function()), + std::dynamic_pointer_cast(message.get_destination_control_function()), message.get_source_control_function()); CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Warning, "[PR]: NACK-ing PGN request for PGN " + isobus::to_string(requestedPGN) + " because no callback could handle it."); } @@ -346,8 +346,8 @@ namespace isobus bool ParameterGroupNumberRequestProtocol::protocol_transmit_message(std::uint32_t, const std::uint8_t *, std::uint32_t, - ControlFunction *, - ControlFunction *, + std::shared_ptr, + std::shared_ptr, TransmitCompleteCallback, void *, DataChunkCallback) @@ -355,7 +355,7 @@ namespace isobus return false; // This protocol is not a transport layer, so just return false } - bool ParameterGroupNumberRequestProtocol::send_acknowledgement(AcknowledgementType type, std::uint32_t parameterGroupNumber, InternalControlFunction *source, ControlFunction *destination) + bool ParameterGroupNumberRequestProtocol::send_acknowledgement(AcknowledgementType type, std::uint32_t parameterGroupNumber, std::shared_ptr source, std::shared_ptr destination) { bool retVal = false; diff --git a/isobus/src/can_partnered_control_function.cpp b/isobus/src/can_partnered_control_function.cpp index ccf330d6..92151005 100644 --- a/isobus/src/can_partnered_control_function.cpp +++ b/isobus/src/can_partnered_control_function.cpp @@ -4,6 +4,7 @@ /// @brief A class that describes a control function on the bus that the stack should communicate /// with. Use these to describe ECUs you want to send messages to. /// @author Adrian Del Grosso +/// @author Daan Steenbergen /// /// @copyright 2022 Adrian Del Grosso //================================================================================================ @@ -17,56 +18,40 @@ namespace isobus { - std::vector PartneredControlFunction::partneredControlFunctionList; + std::vector> PartneredControlFunction::partneredControlFunctionList; bool PartneredControlFunction::anyPartnerNeedsInitializing = false; PartneredControlFunction::PartneredControlFunction(std::uint8_t CANPort, const std::vector NAMEFilters) : - ControlFunction(NAME(0), NULL_CAN_ADDRESS, CANPort), - NAMEFilterList(NAMEFilters), - initialized(false) + ControlFunction(NAME(0), NULL_CAN_ADDRESS, CANPort, Type::Partnered), + NAMEFilterList(NAMEFilters) { const std::lock_guard lock(ControlFunction::controlFunctionProcessingMutex); - bool emptyPartnerSlotFound = false; - controlFunctionType = Type::Partnered; - - for (auto &partner : partneredControlFunctionList) - { - if (nullptr == partner) - { - partner = this; - emptyPartnerSlotFound = true; - break; - } - } - - if (!emptyPartnerSlotFound) - { - partneredControlFunctionList.push_back(this); - } anyPartnerNeedsInitializing = true; } - PartneredControlFunction::~PartneredControlFunction() + std::shared_ptr PartneredControlFunction::create(std::uint8_t CANPort, const std::vector NAMEFilters) { - const std::lock_guard lock(ControlFunction::controlFunctionProcessingMutex); - if (0 != partneredControlFunctionList.size()) - { - auto thisObject = std::find(partneredControlFunctionList.begin(), partneredControlFunctionList.end(), this); + // Unfortunately, we can't use `std::make_shared` here because the constructor is meant to be protected + auto createdControlFunction = std::shared_ptr(new PartneredControlFunction(CANPort, NAMEFilters)); + partneredControlFunctionList.push_back(createdControlFunction); + return createdControlFunction; + } - if (partneredControlFunctionList.end() != thisObject) - { - *thisObject = nullptr; // Don't erase, in case the object was already deleted. Just make room for a new partner. - CANNetworkManager::CANNetwork.on_partner_deleted(this, {}); // Tell the network manager to purge this partner from all tables - } - } + bool PartneredControlFunction::destroy(std::uint32_t expectedRefCount) + { + std::unique_lock lock(controlFunctionProcessingMutex); + partneredControlFunctionList.erase(std::find(partneredControlFunctionList.begin(), partneredControlFunctionList.end(), shared_from_this())); + lock.unlock(); + + return ControlFunction::destroy(expectedRefCount); } - void PartneredControlFunction::add_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, InternalControlFunction *internalControlFunction) + void PartneredControlFunction::add_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, std::shared_ptr internalControlFunction) { parameterGroupNumberCallbacks.emplace_back(parameterGroupNumber, callback, parent, internalControlFunction); } - void PartneredControlFunction::remove_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, InternalControlFunction *internalControlFunction) + void PartneredControlFunction::remove_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, std::shared_ptr internalControlFunction) { ParameterGroupNumberCallbackData tempObject(parameterGroupNumber, callback, parent, internalControlFunction); auto callbackLocation = std::find(parameterGroupNumberCallbacks.begin(), parameterGroupNumberCallbacks.end(), tempObject); @@ -199,9 +184,9 @@ namespace isobus return retVal; } - PartneredControlFunction *PartneredControlFunction::get_partnered_control_function(std::size_t index) + std::shared_ptr PartneredControlFunction::get_partnered_control_function(std::size_t index) { - PartneredControlFunction *retVal = nullptr; + std::shared_ptr retVal = nullptr; if (index < get_number_partnered_control_functions()) { diff --git a/isobus/src/can_transport_protocol.cpp b/isobus/src/can_transport_protocol.cpp index 96a95492..a9120b2d 100644 --- a/isobus/src/can_transport_protocol.cpp +++ b/isobus/src/can_transport_protocol.cpp @@ -150,14 +150,14 @@ namespace isobus (nullptr != message.get_destination_control_function()) && (ControlFunction::Type::Internal == message.get_destination_control_function()->get_type())) { - abort_session(pgn, ConnectionAbortReason::AlreadyInCMSession, reinterpret_cast(message.get_destination_control_function()), message.get_source_control_function()); + abort_session(pgn, ConnectionAbortReason::AlreadyInCMSession, std::dynamic_pointer_cast(message.get_destination_control_function()), message.get_source_control_function()); CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Error, "[TP]: Sent abort, RTS when already in CM session"); } else if ((activeSessions.size() >= CANNetworkConfiguration::get_max_number_transport_protcol_sessions()) && (nullptr != message.get_destination_control_function()) && (ControlFunction::Type::Internal == message.get_destination_control_function()->get_type())) { - abort_session(pgn, ConnectionAbortReason::SystemResourcesNeeded, reinterpret_cast(message.get_destination_control_function()), message.get_source_control_function()); + abort_session(pgn, ConnectionAbortReason::SystemResourcesNeeded, std::dynamic_pointer_cast(message.get_destination_control_function()), message.get_source_control_function()); CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Error, "[TP]: Sent abort, No Sessions Available"); } } @@ -196,7 +196,7 @@ namespace isobus { // The session exists, but we're probably already in the TxDataSession state. Need to abort // In the case of Rx'ing a CTS, we're the source in the session - abort_session(pgn, ConnectionAbortReason::ClearToSendReceivedWhileTransferInProgress, reinterpret_cast(message.get_destination_control_function()), message.get_source_control_function()); + abort_session(pgn, ConnectionAbortReason::ClearToSendReceivedWhileTransferInProgress, std::dynamic_pointer_cast(message.get_destination_control_function()), message.get_source_control_function()); CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Error, "[TP]: Sent abort, CTS while in data session, PGN: " + isobus::to_string(pgn)); } } @@ -204,7 +204,7 @@ namespace isobus { // We got a CTS but no session exists. Aborting clears up the situation faster than waiting for them to timeout // In the case of Rx'ing a CTS, we're the source in the session - abort_session(pgn, ConnectionAbortReason::AnyOtherError, reinterpret_cast(message.get_destination_control_function()), message.get_source_control_function()); + abort_session(pgn, ConnectionAbortReason::AnyOtherError, std::dynamic_pointer_cast(message.get_destination_control_function()), message.get_source_control_function()); CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Error, "[TP]: Sent abort, CTS With no matching session, PGN: " + isobus::to_string(pgn)); } } @@ -232,14 +232,14 @@ namespace isobus } else { - abort_session(pgn, ConnectionAbortReason::AnyOtherError, reinterpret_cast(message.get_destination_control_function()), message.get_source_control_function()); + abort_session(pgn, ConnectionAbortReason::AnyOtherError, std::dynamic_pointer_cast(message.get_destination_control_function()), message.get_source_control_function()); close_session(session, false); CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Error, "[TP]: Sent abort, received EOM in wrong session state, PGN: " + isobus::to_string(pgn)); } } else { - abort_session(pgn, ConnectionAbortReason::AnyOtherError, reinterpret_cast(message.get_destination_control_function()), message.get_source_control_function()); + abort_session(pgn, ConnectionAbortReason::AnyOtherError, std::dynamic_pointer_cast(message.get_destination_control_function()), message.get_source_control_function()); CANStackLogger::CAN_stack_log(CANStackLogger::LoggingLevel::Error, "[TP]: Sent abort, received EOM without matching session, PGN: " + isobus::to_string(pgn)); } } @@ -352,8 +352,8 @@ namespace isobus bool TransportProtocolManager::protocol_transmit_message(std::uint32_t parameterGroupNumber, const std::uint8_t *dataBuffer, std::uint32_t messageLength, - ControlFunction *source, - ControlFunction *destination, + std::shared_ptr source, + std::shared_ptr destination, TransmitCompleteCallback sessionCompleteCallback, void *parentPointer, DataChunkCallback frameChunkCallback) @@ -437,8 +437,8 @@ namespace isobus if (nullptr != session) { - InternalControlFunction *myControlFunction; - ControlFunction *partnerControlFunction; + std::shared_ptr myControlFunction; + std::shared_ptr partnerControlFunction; std::array data; std::uint32_t pgn = session->sessionMessage.get_identifier().get_parameter_group_number(); @@ -471,7 +471,7 @@ namespace isobus return retVal; } - bool TransportProtocolManager::abort_session(std::uint32_t parameterGroupNumber, ConnectionAbortReason reason, InternalControlFunction *source, ControlFunction *destination) + bool TransportProtocolManager::abort_session(std::uint32_t parameterGroupNumber, ConnectionAbortReason reason, std::shared_ptr source, std::shared_ptr destination) { std::array data; @@ -515,7 +515,7 @@ namespace isobus { session->sessionCompleteCallback(session->sessionMessage.get_identifier().get_parameter_group_number(), session->get_message_data_length(), - reinterpret_cast(session->sessionMessage.get_source_control_function()), + std::dynamic_pointer_cast(session->sessionMessage.get_source_control_function()), session->sessionMessage.get_destination_control_function(), success, session->parent); @@ -539,7 +539,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::TransportProtocolCommand), dataBuffer, CAN_DATA_LENGTH, - reinterpret_cast(session->sessionMessage.get_source_control_function()), + std::dynamic_pointer_cast(session->sessionMessage.get_source_control_function()), nullptr, CANIdentifier::CANPriority::PriorityDefault6); } @@ -575,7 +575,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::TransportProtocolCommand), dataBuffer, CAN_DATA_LENGTH, - reinterpret_cast(session->sessionMessage.get_destination_control_function()), + std::dynamic_pointer_cast(session->sessionMessage.get_destination_control_function()), session->sessionMessage.get_source_control_function(), CANIdentifier::CANPriority::PriorityDefault6); } @@ -599,7 +599,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::TransportProtocolCommand), dataBuffer, CAN_DATA_LENGTH, - reinterpret_cast(session->sessionMessage.get_source_control_function()), + std::dynamic_pointer_cast(session->sessionMessage.get_source_control_function()), session->sessionMessage.get_destination_control_function(), CANIdentifier::CANPriority::PriorityDefault6); } @@ -631,7 +631,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::TransportProtocolCommand), dataBuffer, CAN_DATA_LENGTH, - reinterpret_cast(session->sessionMessage.get_destination_control_function()), + std::dynamic_pointer_cast(session->sessionMessage.get_destination_control_function()), session->sessionMessage.get_source_control_function(), CANIdentifier::CANPriority::PriorityDefault6); } @@ -652,7 +652,7 @@ namespace isobus } } - bool TransportProtocolManager::get_session(TransportProtocolSession *&session, ControlFunction *source, ControlFunction *destination) + bool TransportProtocolManager::get_session(TransportProtocolSession *&session, std::shared_ptr source, std::shared_ptr destination) { session = nullptr; @@ -668,7 +668,7 @@ namespace isobus return (nullptr != session); } - bool TransportProtocolManager::get_session(TransportProtocolSession *&session, ControlFunction *source, ControlFunction *destination, std::uint32_t parameterGroupNumber) + bool TransportProtocolManager::get_session(TransportProtocolSession *&session, std::shared_ptr source, std::shared_ptr destination, std::uint32_t parameterGroupNumber) { bool retVal = false; session = nullptr; @@ -800,7 +800,7 @@ namespace isobus if (CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::TransportProtocolData), dataBuffer, CAN_DATA_LENGTH, - reinterpret_cast(session->sessionMessage.get_source_control_function()), + std::dynamic_pointer_cast(session->sessionMessage.get_source_control_function()), session->sessionMessage.get_destination_control_function(), CANIdentifier::CANPriority::PriorityLowest7)) { diff --git a/isobus/src/isobus_diagnostic_protocol.cpp b/isobus/src/isobus_diagnostic_protocol.cpp index ebc03c4c..b5abad21 100644 --- a/isobus/src/isobus_diagnostic_protocol.cpp +++ b/isobus/src/isobus_diagnostic_protocol.cpp @@ -436,7 +436,7 @@ namespace isobus softwareIdentificationFields[index] = value; } - bool DiagnosticProtocol::suspend_broadcasts(std::uint8_t canChannelIndex, InternalControlFunction *sourceControlFunction, std::uint16_t suspendTime_seconds) + bool DiagnosticProtocol::suspend_broadcasts(std::uint8_t canChannelIndex, std::shared_ptr sourceControlFunction, std::uint16_t suspendTime_seconds) { bool retVal = false; @@ -740,8 +740,8 @@ namespace isobus bool DiagnosticProtocol::protocol_transmit_message(std::uint32_t, const std::uint8_t *, std::uint32_t, - ControlFunction *, - ControlFunction *, + std::shared_ptr, + std::shared_ptr, TransmitCompleteCallback, void *, DataChunkCallback) @@ -808,7 +808,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::DiagnosticMessage1), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get()); + myControlFunction); } else { @@ -830,7 +830,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::DiagnosticMessage1), buffer.data(), payloadSize, - myControlFunction.get()); + myControlFunction); } } } @@ -896,7 +896,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::DiagnosticMessage2), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get()); + myControlFunction); } else { @@ -918,7 +918,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::DiagnosticMessage2), buffer.data(), payloadSize, - myControlFunction.get()); + myControlFunction); } } } @@ -940,12 +940,12 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::DiagnosticProtocolIdentification), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get()); + myControlFunction); } return retVal; } - bool DiagnosticProtocol::send_dm13_announce_suspension(InternalControlFunction *sourceControlFunction, std::uint16_t suspendTime_seconds) + bool DiagnosticProtocol::send_dm13_announce_suspension(std::shared_ptr sourceControlFunction, std::uint16_t suspendTime_seconds) { const std::array buffer = { 0xFF, @@ -976,7 +976,7 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUIdentificationInformation), buffer.data(), buffer.size(), - myControlFunction.get()); + myControlFunction); } bool DiagnosticProtocol::send_product_identification() @@ -987,7 +987,7 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ProductIdentification), buffer.data(), buffer.size(), - myControlFunction.get()); + myControlFunction); } bool DiagnosticProtocol::send_software_identification() @@ -1008,7 +1008,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::SoftwareIdentification), buffer.data(), buffer.size(), - myControlFunction.get()); + myControlFunction); } return retVal; } @@ -1064,7 +1064,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::DiagnosticMessage22), buffer.data(), buffer.size(), - myControlFunction.get(), + myControlFunction, currentMessageData.destination); if (retVal) { @@ -1079,7 +1079,7 @@ namespace isobus { if ((((nullptr == message.get_destination_control_function()) && (BROADCAST_CAN_ADDRESS == message.get_identifier().get_destination_address())) || - (message.get_destination_control_function() == myControlFunction.get()))) + (message.get_destination_control_function() == myControlFunction))) { switch (message.get_identifier().get_parameter_group_number()) { @@ -1228,7 +1228,7 @@ namespace isobus } bool DiagnosticProtocol::process_parameter_group_number_request(std::uint32_t parameterGroupNumber, - ControlFunction *requestingControlFunction, + std::shared_ptr requestingControlFunction, bool &acknowledge, AcknowledgementType &acknowledgementType) { @@ -1302,7 +1302,7 @@ namespace isobus } bool DiagnosticProtocol::process_parameter_group_number_request(std::uint32_t parameterGroupNumber, - ControlFunction *requestingControlFunction, + std::shared_ptr requestingControlFunction, bool &acknowledge, AcknowledgementType &acknowledgementType, void *parentPointer) diff --git a/isobus/src/isobus_functionalities.cpp b/isobus/src/isobus_functionalities.cpp index b96f1450..d984d64c 100644 --- a/isobus/src/isobus_functionalities.cpp +++ b/isobus/src/isobus_functionalities.cpp @@ -829,7 +829,7 @@ namespace isobus } bool ControlFunctionFunctionalities::pgn_request_handler(std::uint32_t parameterGroupNumber, - ControlFunction *, + std::shared_ptr, bool &acknowledge, AcknowledgementType &, void *parentPointer) @@ -860,7 +860,7 @@ namespace isobus transmitSuccessful = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ControlFunctionFunctionalities), messageBuffer.data(), messageBuffer.size(), - targetInterface->myControlFunction.get(), + targetInterface->myControlFunction, nullptr); } diff --git a/isobus/src/isobus_guidance_interface.cpp b/isobus/src/isobus_guidance_interface.cpp index 3fd825ec..b3d15ab1 100644 --- a/isobus/src/isobus_guidance_interface.cpp +++ b/isobus/src/isobus_guidance_interface.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace isobus { @@ -36,8 +37,8 @@ namespace isobus std::shared_ptr destination, bool enableSendingSystemCommandPeriodically, bool enableSendingMachineInfoPeriodically) : - guidanceMachineInfoTransmitData(GuidanceMachineInfo(enableSendingMachineInfoPeriodically ? source.get() : nullptr)), - guidanceSystemCommandTransmitData(GuidanceSystemCommand(enableSendingSystemCommandPeriodically ? source.get() : nullptr)), + guidanceMachineInfoTransmitData(GuidanceMachineInfo(enableSendingMachineInfoPeriodically ? source : nullptr)), + guidanceSystemCommandTransmitData(GuidanceSystemCommand(enableSendingSystemCommandPeriodically ? source : nullptr)), txFlags(static_cast(TransmitFlags::NumberOfFlags), process_flags, this), destinationControlFunction(destination) { @@ -52,7 +53,7 @@ namespace isobus } } - AgriculturalGuidanceInterface::GuidanceSystemCommand::GuidanceSystemCommand(ControlFunction *sender) : + AgriculturalGuidanceInterface::GuidanceSystemCommand::GuidanceSystemCommand(std::shared_ptr sender) : controlFunction(sender) { } @@ -87,7 +88,7 @@ namespace isobus return commandedCurvature; } - ControlFunction *AgriculturalGuidanceInterface::GuidanceSystemCommand::get_sender_control_function() const + std::shared_ptr AgriculturalGuidanceInterface::GuidanceSystemCommand::get_sender_control_function() const { return controlFunction; } @@ -102,7 +103,7 @@ namespace isobus return timestamp_ms; } - AgriculturalGuidanceInterface::GuidanceMachineInfo::GuidanceMachineInfo(ControlFunction *sender) : + AgriculturalGuidanceInterface::GuidanceMachineInfo::GuidanceMachineInfo(std::shared_ptr sender) : controlFunction(sender) { } @@ -227,7 +228,7 @@ namespace isobus return guidanceSystemRemoteEngageSwitchStatus; } - ControlFunction *AgriculturalGuidanceInterface::GuidanceMachineInfo::get_sender_control_function() const + std::shared_ptr AgriculturalGuidanceInterface::GuidanceMachineInfo::get_sender_control_function() const { return controlFunction; } @@ -340,8 +341,8 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::AgriculturalGuidanceSystemCommand), buffer.data(), buffer.size(), - static_cast(guidanceSystemCommandTransmitData.get_sender_control_function()), - destinationControlFunction.get(), + std::dynamic_pointer_cast(guidanceSystemCommandTransmitData.get_sender_control_function()), + destinationControlFunction, CANIdentifier::Priority3); } return retVal; @@ -389,8 +390,8 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::AgriculturalGuidanceMachineInfo), buffer.data(), buffer.size(), - static_cast(guidanceMachineInfoTransmitData.get_sender_control_function()), - destinationControlFunction.get(), + std::dynamic_pointer_cast(guidanceMachineInfoTransmitData.get_sender_control_function()), + destinationControlFunction, CANIdentifier::Priority3); } return retVal; diff --git a/isobus/src/isobus_language_command_interface.cpp b/isobus/src/isobus_language_command_interface.cpp index a53b73b8..7b674873 100644 --- a/isobus/src/isobus_language_command_interface.cpp +++ b/isobus/src/isobus_language_command_interface.cpp @@ -74,7 +74,7 @@ namespace isobus if ((nullptr != pgnRequest) && initialized) { - retVal = ParameterGroupNumberRequestProtocol::request_parameter_group_number(static_cast(CANLibParameterGroupNumber::LanguageCommand), myControlFunction.get(), myPartner.get()); + retVal = ParameterGroupNumberRequestProtocol::request_parameter_group_number(static_cast(CANLibParameterGroupNumber::LanguageCommand), myControlFunction, myPartner); } return retVal; } diff --git a/isobus/src/isobus_shortcut_button_interface.cpp b/isobus/src/isobus_shortcut_button_interface.cpp index e26157b0..398cf840 100644 --- a/isobus/src/isobus_shortcut_button_interface.cpp +++ b/isobus/src/isobus_shortcut_button_interface.cpp @@ -229,7 +229,7 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::AllImplementsStopOperationsSwitchState), buffer.data(), buffer.size(), - sourceControlFunction.get(), + sourceControlFunction, nullptr, CANIdentifier::Priority3); } diff --git a/isobus/src/isobus_task_controller_client.cpp b/isobus/src/isobus_task_controller_client.cpp index c7fbf298..207f6a94 100644 --- a/isobus/src/isobus_task_controller_client.cpp +++ b/isobus/src/isobus_task_controller_client.cpp @@ -617,8 +617,8 @@ namespace isobus transmitSuccessful = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ProcessData), nullptr, dataLength, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::CANPriority::PriorityLowest7, process_tx_callback, this, @@ -1685,8 +1685,8 @@ namespace isobus void TaskControllerClient::process_tx_callback(std::uint32_t parameterGroupNumber, std::uint32_t, - InternalControlFunction *, - ControlFunction *destinationControlFunction, + std::shared_ptr, + std::shared_ptr destinationControlFunction, bool successful, void *parentPointer) { @@ -1731,8 +1731,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ProcessData), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get()); + myControlFunction, + partnerControlFunction); } bool TaskControllerClient::send_object_pool_activate() const @@ -1756,8 +1756,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ProcessData), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get()); + myControlFunction, + partnerControlFunction); } bool TaskControllerClient::send_pdack(std::uint16_t elementNumber, std::uint16_t ddi) const @@ -1774,8 +1774,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ProcessData), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get()); + myControlFunction, + partnerControlFunction); } bool TaskControllerClient::send_request_localization_label() const @@ -1806,8 +1806,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ProcessData), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get()); + myControlFunction, + partnerControlFunction); } bool TaskControllerClient::send_request_structure_label() const @@ -1835,8 +1835,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ProcessData), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get()); + myControlFunction, + partnerControlFunction); } bool TaskControllerClient::send_status() const @@ -1853,8 +1853,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ProcessData), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get()); + myControlFunction, + partnerControlFunction); } bool TaskControllerClient::send_value_command(std::uint16_t elementNumber, std::uint16_t ddi, std::uint32_t value) const @@ -1871,8 +1871,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ProcessData), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get()); + myControlFunction, + partnerControlFunction); } bool TaskControllerClient::send_version_request() const @@ -1887,7 +1887,7 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::WorkingSetMaster), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), + myControlFunction, nullptr); } @@ -1998,7 +1998,7 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ProcessData), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), + myControlFunction, nullptr); } diff --git a/isobus/src/isobus_virtual_terminal_client.cpp b/isobus/src/isobus_virtual_terminal_client.cpp index dd4db823..32135cab 100644 --- a/isobus/src/isobus_virtual_terminal_client.cpp +++ b/isobus/src/isobus_virtual_terminal_client.cpp @@ -249,8 +249,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -267,8 +267,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -285,8 +285,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -303,8 +303,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -321,8 +321,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -347,8 +347,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -365,8 +365,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -386,8 +386,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), buffer.size(), - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -404,8 +404,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -422,8 +422,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -442,8 +442,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -472,8 +472,8 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), buffer.size(), - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } return retVal; @@ -497,8 +497,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -515,8 +515,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -533,8 +533,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -551,8 +551,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -569,8 +569,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -587,8 +587,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -605,8 +605,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -632,8 +632,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -650,8 +650,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -668,8 +668,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -686,8 +686,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -704,8 +704,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -722,8 +722,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -740,8 +740,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -758,8 +758,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -776,8 +776,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -794,8 +794,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -813,8 +813,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), buffer.size(), - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -831,8 +831,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -849,8 +849,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -867,8 +867,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -885,8 +885,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -903,8 +903,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -921,8 +921,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -939,8 +939,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -957,8 +957,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -975,8 +975,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -993,8 +993,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -1011,8 +1011,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -1029,8 +1029,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -1061,8 +1061,8 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), buffer.size(), - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } return retVal; @@ -1093,8 +1093,8 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), buffer.size(), - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } return retVal; @@ -1113,8 +1113,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -1140,8 +1140,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -1171,8 +1171,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), buffer.size(), - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -1195,8 +1195,8 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } return retVal; @@ -1215,8 +1215,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -1233,8 +1233,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -1251,8 +1251,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -1269,8 +1269,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -1843,8 +1843,8 @@ namespace isobus bool transmitSuccessful = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), nullptr, objectPools[i].objectPoolSize + 1, // Account for Mux byte - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::CANPriority::PriorityLowest7, process_callback, this, @@ -1981,8 +1981,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2035,8 +2035,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2053,8 +2053,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2071,8 +2071,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2089,8 +2089,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2107,8 +2107,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2125,8 +2125,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2143,8 +2143,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2161,8 +2161,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2179,8 +2179,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2197,8 +2197,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2215,8 +2215,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2233,8 +2233,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2251,8 +2251,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2264,8 +2264,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), buffer.size(), - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2277,8 +2277,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), buffer.size(), - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2290,8 +2290,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), buffer.size(), - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2308,8 +2308,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2326,7 +2326,7 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::WorkingSetMaster), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), + myControlFunction, nullptr, CANIdentifier::PriorityLowest7); } @@ -2342,8 +2342,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), buffer.size(), - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2369,8 +2369,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2387,7 +2387,7 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), + myControlFunction, nullptr, CANIdentifier::Priority3); } @@ -2405,8 +2405,8 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::PriorityLowest7); } @@ -2463,8 +2463,8 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), + myControlFunction, + partnerControlFunction, CANIdentifier::Priority3); } else @@ -2472,7 +2472,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::VirtualTerminalToECU), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), + myControlFunction, nullptr, CANIdentifier::Priority3); } @@ -3333,8 +3333,8 @@ namespace isobus void VirtualTerminalClient::process_callback(std::uint32_t parameterGroupNumber, std::uint32_t, - InternalControlFunction *, - ControlFunction *destinationControlFunction, + std::shared_ptr, + std::shared_ptr destinationControlFunction, bool successful, void *parentPointer) { diff --git a/isobus/src/nmea2000_fast_packet_protocol.cpp b/isobus/src/nmea2000_fast_packet_protocol.cpp index 52e351ff..b3ae547e 100644 --- a/isobus/src/nmea2000_fast_packet_protocol.cpp +++ b/isobus/src/nmea2000_fast_packet_protocol.cpp @@ -61,13 +61,13 @@ namespace isobus } } - void FastPacketProtocol::register_multipacket_message_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, InternalControlFunction *internalControlFunction) + void FastPacketProtocol::register_multipacket_message_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, std::shared_ptr internalControlFunction) { parameterGroupNumberCallbacks.push_back(ParameterGroupNumberCallbackData(parameterGroupNumber, callback, parent, internalControlFunction)); CANNetworkManager::CANNetwork.add_protocol_parameter_group_number_callback(parameterGroupNumber, process_message, this); } - void FastPacketProtocol::remove_multipacket_message_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, InternalControlFunction *internalControlFunction) + void FastPacketProtocol::remove_multipacket_message_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, std::shared_ptr internalControlFunction) { ParameterGroupNumberCallbackData tempObject(parameterGroupNumber, callback, parent, internalControlFunction); auto callbackLocation = std::find(parameterGroupNumberCallbacks.begin(), parameterGroupNumberCallbacks.end(), tempObject); @@ -81,8 +81,8 @@ namespace isobus bool FastPacketProtocol::send_multipacket_message(std::uint32_t parameterGroupNumber, const std::uint8_t *data, std::uint8_t messageLength, - InternalControlFunction *source, - ControlFunction *destination, + std::shared_ptr source, + std::shared_ptr destination, CANIdentifier::CANPriority priority, TransmitCompleteCallback txCompleteCallback, void *parentPointer, @@ -221,7 +221,7 @@ namespace isobus return retVal; } - bool FastPacketProtocol::get_session(FastPacketProtocolSession *&returnedSession, std::uint32_t parameterGroupNumber, ControlFunction *source, ControlFunction *destination) + bool FastPacketProtocol::get_session(FastPacketProtocolSession *&returnedSession, std::uint32_t parameterGroupNumber, std::shared_ptr source, std::shared_ptr destination) { returnedSession = nullptr; std::unique_lock lock(sessionMutex); @@ -376,7 +376,7 @@ namespace isobus { session->sessionCompleteCallback(session->sessionMessage.get_identifier().get_parameter_group_number(), session->get_message_data_length(), - reinterpret_cast(session->sessionMessage.get_source_control_function()), + std::dynamic_pointer_cast(session->sessionMessage.get_source_control_function()), session->sessionMessage.get_destination_control_function(), success, session->parent); @@ -386,8 +386,8 @@ namespace isobus bool FastPacketProtocol::protocol_transmit_message(std::uint32_t, const std::uint8_t *, std::uint32_t, - ControlFunction *, - ControlFunction *, + std::shared_ptr, + std::shared_ptr, TransmitCompleteCallback, void *, DataChunkCallback) @@ -491,7 +491,7 @@ namespace isobus if (CANNetworkManager::CANNetwork.send_can_message(session->sessionMessage.get_identifier().get_parameter_group_number(), dataBuffer.data(), CAN_DATA_LENGTH, - reinterpret_cast(session->sessionMessage.get_source_control_function()), + std::dynamic_pointer_cast(session->sessionMessage.get_source_control_function()), session->sessionMessage.get_destination_control_function(), session->sessionMessage.get_identifier().get_priority(), nullptr, diff --git a/sphinx/source/Tutorials/Adding a Destination.rst b/sphinx/source/Tutorials/Adding a Destination.rst index b8300e7c..83d6c579 100644 --- a/sphinx/source/Tutorials/Adding a Destination.rst +++ b/sphinx/source/Tutorials/Adding a Destination.rst @@ -53,7 +53,7 @@ The main reason I use shared_ptr is because that is what the interface for a Vir std::shared_ptr myPartner = nullptr; - myPartner = std::make_shared(0, myPartnerFilter); + myPartner = isobus::PartneredControlFunction::create(0, myPartnerFilter); Above, we've just instantiated a partner *on CAN channel 0* using the filter we made in the previous step. @@ -145,10 +145,10 @@ The final program for this tutorial (including the code from the previous Hello myPartnerFilter.push_back(virtualTerminalFilter); // Create our InternalControlFunction - myECU = std::make_shared(myNAME, 0x1C, 0); + myECU = isobus::InternalControlFunction::create(myNAME, 0x1C, 0); // Create our PartneredControlFunction - myPartner = std::make_shared(0, myPartnerFilter); + myPartner = isobus::PartneredControlFunction::create(0, myPartnerFilter); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); diff --git a/sphinx/source/Tutorials/Receiving Messages.rst b/sphinx/source/Tutorials/Receiving Messages.rst index e6d83cc0..403f55b5 100644 --- a/sphinx/source/Tutorials/Receiving Messages.rst +++ b/sphinx/source/Tutorials/Receiving Messages.rst @@ -125,7 +125,7 @@ So, our updated tutorial program now should look like this: myNAME.set_manufacturer_code(64); // Create our InternalControlFunction - myECU = std::make_shared(myNAME, 0x1C, 0); + myECU = isobus::InternalControlFunction::create(myNAME, 0x1C, 0); // Define a NAME filter for our partner std::vector myPartnerFilter; @@ -136,7 +136,7 @@ So, our updated tutorial program now should look like this: isobus::CANNetworkManager::CANNetwork.add_global_parameter_group_number_callback(0xEF00, propa_callback, nullptr); // Create our PartneredControlFunction - myPartner = std::make_shared(0, myPartnerFilter); + myPartner = isobus::PartneredControlFunction::create(0, myPartnerFilter); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); diff --git a/sphinx/source/Tutorials/The ISOBUS Hello World.rst b/sphinx/source/Tutorials/The ISOBUS Hello World.rst index 4b78fb44..b4149a3e 100644 --- a/sphinx/source/Tutorials/The ISOBUS Hello World.rst +++ b/sphinx/source/Tutorials/The ISOBUS Hello World.rst @@ -139,7 +139,7 @@ In this example, I'll use a shared_ptr to store my InternalControlFunction, but myNAME.set_manufacturer_code(64); // Create our InternalControlFunction - myECU = std::make_shared(myNAME, 0x1C, 0); + myECU = isobus::InternalControlFunction::create(myNAME, 0x1C, 0); return 0; } @@ -240,7 +240,7 @@ Let's see what we've got so far: myNAME.set_manufacturer_code(64); // Create our InternalControlFunction - myECU = std::make_shared(myNAME, 0x1C, 0); + myECU = isobus::InternalControlFunction::create(myNAME, 0x1C, 0); return 0; } @@ -305,7 +305,7 @@ Make sure to include `csignal`. myNAME.set_manufacturer_code(64); // Create our InternalControlFunction - myECU = std::make_shared(myNAME, 0x1C, 0); + myECU = isobus::InternalControlFunction::create(myNAME, 0x1C, 0); // Clean up the threads isobus::CANHardwareInterface::stop(); @@ -373,7 +373,7 @@ The total result: myNAME.set_manufacturer_code(64); // Create our InternalControlFunction - myECU = std::make_shared(myNAME, 0x1C, 0); + myECU = isobus::InternalControlFunction::create(myNAME, 0x1C, 0); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); diff --git a/sphinx/source/Tutorials/Virtual Terminal Basics.rst b/sphinx/source/Tutorials/Virtual Terminal Basics.rst index 1c9e3310..bb2b2802 100644 --- a/sphinx/source/Tutorials/Virtual Terminal Basics.rst +++ b/sphinx/source/Tutorials/Virtual Terminal Basics.rst @@ -116,8 +116,8 @@ Create the file `main.cpp` as shown below inside that folder with the requisite const isobus::NAMEFilter filterVirtualTerminal(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::VirtualTerminal)); const std::vector vtNameFilters = { filterVirtualTerminal }; - auto TestInternalECU = std::make_shared(TestDeviceNAME, 0x1C, 0); - auto TestPartnerVT = std::make_shared(0, vtNameFilters); + auto TestInternalECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x1C, 0); + auto TestPartnerVT = isobus::PartneredControlFunction::create(0, vtNameFilters); while (running) { @@ -520,8 +520,8 @@ Here's the final code for this example: const isobus::NAMEFilter filterVirtualTerminal(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::VirtualTerminal)); const std::vector vtNameFilters = { filterVirtualTerminal }; - auto TestInternalECU = std::make_shared(TestDeviceNAME, 0x1C, 0); - auto TestPartnerVT = std::make_shared(0, vtNameFilters); + auto TestInternalECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x1C, 0); + auto TestPartnerVT = isobus::PartneredControlFunction::create(0, vtNameFilters); TestVirtualTerminalClient = std::make_shared(TestPartnerVT, TestInternalECU); TestVirtualTerminalClient->set_object_pool(0, isobus::VirtualTerminalClient::VTVersion::Version3, testPool.data(), testPool.size(), objectPoolHash); diff --git a/test/address_claim_tests.cpp b/test/address_claim_tests.cpp index 968977c3..b4bd215a 100644 --- a/test/address_claim_tests.cpp +++ b/test/address_claim_tests.cpp @@ -15,8 +15,8 @@ using namespace isobus; TEST(ADDRESS_CLAIM_TESTS, PartneredClaim) { - std::shared_ptr firstDevice = std::make_shared(); - std::shared_ptr secondDevice = std::make_shared(); + auto firstDevice = std::make_shared(); + auto secondDevice = std::make_shared(); CANHardwareInterface::set_number_of_can_channels(2); CANHardwareInterface::assign_can_channel_frame_handler(0, firstDevice); CANHardwareInterface::assign_can_channel_frame_handler(1, secondDevice); @@ -34,7 +34,7 @@ TEST(ADDRESS_CLAIM_TESTS, PartneredClaim) firstName.set_function_instance(0); firstName.set_device_class_instance(0); firstName.set_manufacturer_code(69); - InternalControlFunction firstInternalECU(firstName, 0x1C, 0); + auto firstInternalECU = InternalControlFunction::create(firstName, 0x1C, 0); isobus::NAME secondName(0); secondName.set_arbitrary_address_capable(true); @@ -46,17 +46,22 @@ TEST(ADDRESS_CLAIM_TESTS, PartneredClaim) secondName.set_function_instance(0); secondName.set_device_class_instance(0); secondName.set_manufacturer_code(69); - InternalControlFunction secondInternalECU2(secondName, 0x1D, 1); + auto secondInternalECU2 = InternalControlFunction::create(secondName, 0x1D, 1); const NAMEFilter filterSecond(NAME::NAMEParameters::FunctionCode, static_cast(NAME::Function::SeatControl)); - PartneredControlFunction firstPartneredSecondECU(0, { filterSecond }); + auto firstPartneredSecondECU = PartneredControlFunction::create(0, { filterSecond }); const isobus::NAMEFilter filterFirst(NAME::NAMEParameters::FunctionCode, static_cast(NAME::Function::CabClimateControl)); - PartneredControlFunction secondPartneredFirstEcu(1, { filterFirst }); + auto secondPartneredFirstEcu = PartneredControlFunction::create(1, { filterFirst }); std::this_thread::sleep_for(std::chrono::milliseconds(500)); - - EXPECT_TRUE(firstPartneredSecondECU.get_address_valid()); - EXPECT_TRUE(secondPartneredFirstEcu.get_address_valid()); + EXPECT_TRUE(firstInternalECU->get_address_valid()); + EXPECT_TRUE(secondInternalECU2->get_address_valid()); + EXPECT_TRUE(firstPartneredSecondECU->get_address_valid()); + EXPECT_TRUE(secondPartneredFirstEcu->get_address_valid()); CANHardwareInterface::stop(); + ASSERT_TRUE(firstPartneredSecondECU->destroy()); + ASSERT_TRUE(secondPartneredFirstEcu->destroy()); + ASSERT_TRUE(firstInternalECU->destroy()); + ASSERT_TRUE(secondInternalECU2->destroy()); } diff --git a/test/cf_functionalities_tests.cpp b/test/cf_functionalities_tests.cpp index f762f951..afe880e8 100644 --- a/test/cf_functionalities_tests.cpp +++ b/test/cf_functionalities_tests.cpp @@ -35,7 +35,7 @@ TEST(CONTROL_FUNCTION_FUNCTIONALITIES_TESTS, CFFunctionalitiesTest) clientNAME.set_industry_group(2); clientNAME.set_function_instance(3); clientNAME.set_function_code(static_cast(NAME::Function::TirePressureControl)); - auto internalECU = std::make_shared(clientNAME, 0x50, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x50, 0); CANMessageFrame testFrame; @@ -49,21 +49,6 @@ TEST(CONTROL_FUNCTION_FUNCTIONALITIES_TESTS, CFFunctionalitiesTest) ASSERT_TRUE(internalECU->get_address_valid()); - // Force claim a partner - testFrame.dataLength = 8; - testFrame.channel = 0; - testFrame.isExtendedFrame = true; - testFrame.identifier = 0x18EEFFF7; - testFrame.data[0] = 0x03; - testFrame.data[1] = 0x04; - testFrame.data[2] = 0x00; - testFrame.data[3] = 0x12; - testFrame.data[4] = 0x00; - testFrame.data[5] = 0x82; - testFrame.data[6] = 0x00; - testFrame.data[7] = 0xA0; - CANNetworkManager::process_receive_can_message_frame(testFrame); - TestControlFunctionFunctionalities cfFunctionalitiesUnderTest(internalECU); std::this_thread::sleep_for(std::chrono::milliseconds(50)); @@ -627,4 +612,7 @@ TEST(CONTROL_FUNCTION_FUNCTIONALITIES_TESTS, CFFunctionalitiesTest) EXPECT_EQ(2, testMessageData.at(17)); // 2 Option bytes EXPECT_EQ(1, testMessageData.at(18)); // 1 Boom EXPECT_EQ(255, testMessageData.at(19)); // 255 Sections + + //! @todo try to reduce the reference count, such that that we don't use destroyed control functions later on + ASSERT_TRUE(internalECU->destroy(3)); } diff --git a/test/core_network_management_tests.cpp b/test/core_network_management_tests.cpp index bc4114c3..aa9f8db6 100644 --- a/test/core_network_management_tests.cpp +++ b/test/core_network_management_tests.cpp @@ -17,10 +17,13 @@ TEST(CORE_TESTS, TestCreateAndDestroyPartners) std::vector vtNameFilters; const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::VirtualTerminal)); - isobus::PartneredControlFunction TestPartner1(0, vtNameFilters); - isobus::PartneredControlFunction *TestPartner2 = new isobus::PartneredControlFunction(0, vtNameFilters); - delete TestPartner2; - auto TestPartner3 = std::make_shared(0, vtNameFilters); + auto testPartner1 = isobus::PartneredControlFunction::create(0, vtNameFilters); + auto testPartner2 = isobus::PartneredControlFunction::create(0, vtNameFilters); + EXPECT_TRUE(testPartner2->destroy()); + auto TestPartner3 = isobus::PartneredControlFunction::create(0, vtNameFilters); + + EXPECT_TRUE(testPartner1->destroy()); + EXPECT_TRUE(TestPartner3->destroy()); } TEST(CORE_TESTS, TestCreateAndDestroyICFs) @@ -36,10 +39,17 @@ TEST(CORE_TESTS, TestCreateAndDestroyICFs) TestDeviceNAME.set_device_class_instance(0); TestDeviceNAME.set_manufacturer_code(64); - isobus::InternalControlFunction TestIcf1(TestDeviceNAME, 0x1C, 0); - auto TestIcf2 = new isobus::InternalControlFunction(TestDeviceNAME, 0x80, 0); - delete TestIcf2; - auto TestIcf3 = std::make_shared(TestDeviceNAME, 0x81, 0); + auto testICF1 = isobus::InternalControlFunction::create(TestDeviceNAME, 0x1C, 0); + + TestDeviceNAME.set_ecu_instance(1); + auto testICF2 = isobus::InternalControlFunction::create(TestDeviceNAME, 0x80, 0); + ASSERT_TRUE(testICF2->destroy()); + + TestDeviceNAME.set_ecu_instance(2); + auto testICF3 = isobus::InternalControlFunction::create(TestDeviceNAME, 0x81, 0); + + ASSERT_TRUE(testICF1->destroy()); + ASSERT_TRUE(testICF3->destroy()); } TEST(CORE_TESTS, BusloadTest) @@ -94,7 +104,7 @@ TEST(CORE_TESTS, CommandedAddress) TestDeviceNAME.set_device_class_instance(0); TestDeviceNAME.set_manufacturer_code(64); - auto testECU = std::make_shared(TestDeviceNAME, 0x43, 0); + auto testECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x43, 0); CANMessageFrame testFrame; diff --git a/test/diagnostic_protocol_tests.cpp b/test/diagnostic_protocol_tests.cpp index ae63ebc9..808c6d13 100644 --- a/test/diagnostic_protocol_tests.cpp +++ b/test/diagnostic_protocol_tests.cpp @@ -36,7 +36,7 @@ TEST(DIAGNOSTIC_PROTOCOL_TESTS, CreateAndDestroyProtocolObjects) { NAME TestDeviceNAME(0); - auto TestInternalECU = std::make_shared(TestDeviceNAME, 0x1C, 0); + auto TestInternalECU = InternalControlFunction::create(TestDeviceNAME, 0x1C, 0); DiagnosticProtocol::assign_diagnostic_protocol_to_internal_control_function(TestInternalECU); DiagnosticProtocol *diagnosticProtocol = DiagnosticProtocol::get_diagnostic_protocol_by_internal_control_function(TestInternalECU); @@ -47,4 +47,6 @@ TEST(DIAGNOSTIC_PROTOCOL_TESTS, CreateAndDestroyProtocolObjects) EXPECT_NO_THROW(DiagnosticProtocol::deassign_all_diagnostic_protocol_to_internal_control_functions()); EXPECT_EQ(nullptr, DiagnosticProtocol::get_diagnostic_protocol_by_internal_control_function(TestInternalECU)); } + + ASSERT_TRUE(TestInternalECU->destroy(2)); } diff --git a/test/guidance_tests.cpp b/test/guidance_tests.cpp index 728c103f..56de0d92 100644 --- a/test/guidance_tests.cpp +++ b/test/guidance_tests.cpp @@ -75,7 +75,7 @@ TEST(GUIDANCE_TESTS, GuidanceMessages) TestDeviceNAME.set_device_class_instance(0); TestDeviceNAME.set_manufacturer_code(64); - auto testECU = std::make_shared(TestDeviceNAME, 0x44, 0); + auto testECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x44, 0); CANMessageFrame testFrame; testFrame.timestamp_us = 0; @@ -217,6 +217,8 @@ TEST(GUIDANCE_TESTS, GuidanceMessages) CANHardwareInterface::stop(); testPlugin.close(); } + + ASSERT_TRUE(testECU->destroy()); } TEST(GUIDANCE_TESTS, ListenOnlyModeAndDecoding) diff --git a/test/isb_tests.cpp b/test/isb_tests.cpp index a6c3d9c1..7977cf93 100644 --- a/test/isb_tests.cpp +++ b/test/isb_tests.cpp @@ -28,7 +28,7 @@ TEST(ISB_TESTS, ShortcutButtonRxTests) clientNAME.set_industry_group(2); clientNAME.set_ecu_instance(4); clientNAME.set_function_code(static_cast(NAME::Function::RateControl)); - auto internalECU = std::make_shared(clientNAME, 0x97, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x97, 0); CANMessageFrame testFrame; @@ -226,6 +226,9 @@ TEST(ISB_TESTS, ShortcutButtonRxTests) interfaceUnderTest.update(); EXPECT_EQ(ShortcutButtonInterface::StopAllImplementOperationsState::PermitAllImplementsToOperationOn, interfaceUnderTest.get_state()); CANHardwareInterface::stop(); + + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + ASSERT_TRUE(internalECU->destroy(2)); } TEST(ISB_TESTS, ShortcutButtonTxTests) @@ -241,7 +244,7 @@ TEST(ISB_TESTS, ShortcutButtonTxTests) clientNAME.set_industry_group(2); clientNAME.set_ecu_instance(4); clientNAME.set_function_code(static_cast(NAME::Function::RateControl)); - auto internalECU = std::make_shared(clientNAME, 0x98, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x98, 0); CANMessageFrame testFrame; @@ -304,4 +307,7 @@ TEST(ISB_TESTS, ShortcutButtonTxTests) EXPECT_EQ(ShortcutButtonInterface::StopAllImplementOperationsState::StopImplementOperations, interfaceUnderTest.get_state()); CANHardwareInterface::stop(); + + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + ASSERT_TRUE(internalECU->destroy(2)); } diff --git a/test/language_command_interface_tests.cpp b/test/language_command_interface_tests.cpp index 3665e349..d334ae86 100644 --- a/test/language_command_interface_tests.cpp +++ b/test/language_command_interface_tests.cpp @@ -13,7 +13,7 @@ using namespace isobus; TEST(LANGUAGE_COMMAND_INTERFACE_TESTS, BasicConstructionAndInit) { NAME clientNAME(0); - auto internalECU = std::make_shared(clientNAME, 0x26, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x26, 0); LanguageCommandInterface interfaceUnderTest(internalECU); EXPECT_EQ(false, interfaceUnderTest.get_initialized()); EXPECT_EQ(false, interfaceUnderTest.send_request_language_command()); @@ -22,6 +22,9 @@ TEST(LANGUAGE_COMMAND_INTERFACE_TESTS, BasicConstructionAndInit) EXPECT_EQ(0, interfaceUnderTest.get_language_command_timestamp()); interfaceUnderTest.initialize(); // double init EXPECT_EQ(true, interfaceUnderTest.get_initialized()); + + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + ASSERT_TRUE(internalECU->destroy(3)); } TEST(LANGUAGE_COMMAND_INTERFACE_TESTS, InvalidICF) @@ -38,15 +41,19 @@ TEST(LANGUAGE_COMMAND_INTERFACE_TESTS, ValidPartner) vtNameFilters.push_back(testFilter); NAME clientNAME(0); - auto internalECU = std::make_shared(clientNAME, 0x26, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x26, 0); - auto vtPartner = std::make_shared(0, vtNameFilters); + auto vtPartner = PartneredControlFunction::create(0, vtNameFilters); LanguageCommandInterface interfaceUnderTest(internalECU, vtPartner); interfaceUnderTest.initialize(); ASSERT_TRUE(interfaceUnderTest.get_initialized()); // Technically our address is bad, so this should still not send //! @todo Test with valid address ASSERT_FALSE(interfaceUnderTest.send_request_language_command()); + + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + ASSERT_TRUE(vtPartner->destroy(2)); + ASSERT_TRUE(internalECU->destroy(3)); } TEST(LANGUAGE_COMMAND_INTERFACE_TESTS, Uninitialized) @@ -58,7 +65,7 @@ TEST(LANGUAGE_COMMAND_INTERFACE_TESTS, Uninitialized) TEST(LANGUAGE_COMMAND_INTERFACE_TESTS, MessageContentParsing) { NAME clientNAME(0); - auto internalECU = std::make_shared(clientNAME, 0x80, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x80, 0); LanguageCommandInterface interfaceUnderTest(internalECU, nullptr); interfaceUnderTest.initialize(); @@ -161,4 +168,7 @@ TEST(LANGUAGE_COMMAND_INTERFACE_TESTS, MessageContentParsing) interfaceUnderTest.process_rx_message(testMessage, nullptr); // Message should have been discarded EXPECT_EQ("pl", interfaceUnderTest.get_language_code()); + + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + ASSERT_TRUE(internalECU->destroy(3)); } diff --git a/test/tc_client_tests.cpp b/test/tc_client_tests.cpp index be797c61..f78edb9a 100644 --- a/test/tc_client_tests.cpp +++ b/test/tc_client_tests.cpp @@ -80,8 +80,8 @@ class DerivedTestTCClient : public TaskControllerClient void test_wrapper_process_tx_callback(std::uint32_t parameterGroupNumber, std::uint32_t dataLength, - InternalControlFunction *sourceControlFunction, - ControlFunction *destinationControlFunction, + std::shared_ptr sourceControlFunction, + std::shared_ptr destinationControlFunction, bool successful, void *parentPointer) { @@ -270,7 +270,7 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, MessageEncoding) NAME clientNAME(0); clientNAME.set_industry_group(2); clientNAME.set_function_code(static_cast(NAME::Function::RateControl)); - auto internalECU = std::make_shared(clientNAME, 0x81, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x84, 0); CANMessageFrame testFrame; @@ -288,7 +288,7 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, MessageEncoding) const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::TaskController)); vtNameFilters.push_back(testFilter); - auto vtPartner = std::make_shared(0, vtNameFilters); + auto tcPartner = PartneredControlFunction::create(0, vtNameFilters); // Force claim a partner testFrame.dataLength = 8; @@ -305,7 +305,7 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, MessageEncoding) testFrame.data[7] = 0xA0; CANNetworkManager::process_receive_can_message_frame(testFrame); - DerivedTestTCClient interfaceUnderTest(vtPartner, internalECU); + DerivedTestTCClient interfaceUnderTest(tcPartner, internalECU); std::this_thread::sleep_for(std::chrono::milliseconds(50)); @@ -315,6 +315,7 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, MessageEncoding) serverTC.read_frame(testFrame); } ASSERT_TRUE(serverTC.get_queue_empty()); + ASSERT_TRUE(tcPartner->get_address_valid()); // Test Working Set Master Message ASSERT_TRUE(interfaceUnderTest.test_wrapper_send_working_set_master()); @@ -478,6 +479,10 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, MessageEncoding) CANHardwareInterface::stop(); CANHardwareInterface::set_number_of_can_channels(0); + + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + ASSERT_TRUE(tcPartner->destroy(3)); + ASSERT_TRUE(internalECU->destroy(3)); } TEST(TASK_CONTROLLER_CLIENT_TESTS, BadPartnerDeathTest) @@ -485,7 +490,7 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, BadPartnerDeathTest) NAME clientNAME(0); clientNAME.set_industry_group(2); clientNAME.set_function_code(static_cast(NAME::Function::RateControl)); - auto internalECU = std::make_shared(clientNAME, 0x81, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x81, 0); DerivedTestTCClient interfaceUnderTest(nullptr, internalECU); ASSERT_FALSE(interfaceUnderTest.get_is_initialized()); EXPECT_DEATH(interfaceUnderTest.initialize(false), ""); @@ -497,10 +502,11 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, BadICFDeathTest) const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::TaskController)); vtNameFilters.push_back(testFilter); - auto vtPartner = std::make_shared(0, vtNameFilters); - DerivedTestTCClient interfaceUnderTest(vtPartner, nullptr); + auto tcPartner = PartneredControlFunction::create(0, vtNameFilters); + DerivedTestTCClient interfaceUnderTest(tcPartner, nullptr); ASSERT_FALSE(interfaceUnderTest.get_is_initialized()); EXPECT_DEATH(interfaceUnderTest.initialize(false), ""); + ASSERT_TRUE(tcPartner->destroy(3)); // Account for the pointer in the TC client and the language interface } TEST(TASK_CONTROLLER_CLIENT_TESTS, BadBinaryPointerDDOPDeathTest) @@ -535,7 +541,7 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, StateMachineTests) clientNAME.set_industry_group(2); clientNAME.set_ecu_instance(1); clientNAME.set_function_code(static_cast(NAME::Function::RateControl)); - auto internalECU = std::make_shared(clientNAME, 0x83, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x83, 0); CANMessageFrame testFrame; @@ -553,7 +559,7 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, StateMachineTests) const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::TaskController)); tcNameFilters.push_back(testFilter); - auto tcPartner = std::make_shared(0, tcNameFilters); + auto tcPartner = PartneredControlFunction::create(0, tcNameFilters); // Force claim a partner testFrame.dataLength = 8; @@ -581,6 +587,7 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, StateMachineTests) serverTC.read_frame(testFrame); } ASSERT_TRUE(serverTC.get_queue_empty()); + ASSERT_TRUE(tcPartner->get_address_valid()); // End boilerplate @@ -966,7 +973,7 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, StateMachineTests) CANNetworkManager::CANNetwork.update(); EXPECT_EQ(interfaceUnderTest.test_wrapper_get_state(), TaskControllerClient::StateMachineState::WaitForDDOPTransfer); // Check ddop transfer callback - interfaceUnderTest.test_wrapper_process_tx_callback(0xCB00, 8, nullptr, reinterpret_cast(tcPartner.get()), false, &interfaceUnderTest); + interfaceUnderTest.test_wrapper_process_tx_callback(0xCB00, 8, nullptr, std::dynamic_pointer_cast(tcPartner), false, &interfaceUnderTest); // In this case it should be disconnected because we passed in false. EXPECT_EQ(interfaceUnderTest.test_wrapper_get_state(), TaskControllerClient::StateMachineState::Disconnected); @@ -975,7 +982,7 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, StateMachineTests) CANNetworkManager::CANNetwork.update(); EXPECT_EQ(interfaceUnderTest.test_wrapper_get_state(), TaskControllerClient::StateMachineState::WaitForDDOPTransfer); // Check ddop transfer callback - interfaceUnderTest.test_wrapper_process_tx_callback(0xCB00, 8, nullptr, reinterpret_cast(tcPartner.get()), true, &interfaceUnderTest); + interfaceUnderTest.test_wrapper_process_tx_callback(0xCB00, 8, nullptr, std::dynamic_pointer_cast(tcPartner), true, &interfaceUnderTest); // In this case it should be disconnected because we passed in false. EXPECT_EQ(interfaceUnderTest.test_wrapper_get_state(), TaskControllerClient::StateMachineState::WaitForObjectPoolTransferResponse); @@ -1117,6 +1124,10 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, StateMachineTests) interfaceUnderTest.terminate(); CANHardwareInterface::stop(); + + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + ASSERT_TRUE(tcPartner->destroy(4)); + ASSERT_TRUE(internalECU->destroy(6)); } TEST(TASK_CONTROLLER_CLIENT_TESTS, ClientSettings) @@ -1151,7 +1162,7 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, TimeoutTests) clientNAME.set_industry_group(2); clientNAME.set_ecu_instance(1); clientNAME.set_function_code(static_cast(NAME::Function::RateControl)); - auto internalECU = std::make_shared(clientNAME, 0x84, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x84, 0); ASSERT_FALSE(internalECU->get_address_valid()); @@ -1159,9 +1170,9 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, TimeoutTests) const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::TaskController)); vtNameFilters.push_back(testFilter); - auto vtPartner = std::make_shared(0, vtNameFilters); + auto tcPartner = PartneredControlFunction::create(0, vtNameFilters); - DerivedTestTCClient interfaceUnderTest(vtPartner, internalECU); + DerivedTestTCClient interfaceUnderTest(tcPartner, internalECU); interfaceUnderTest.initialize(false); // Wait a while to build up some run time for testing timeouts later @@ -1337,6 +1348,10 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, TimeoutTests) EXPECT_EQ(interfaceUnderTest.test_wrapper_get_state(), TaskControllerClient::StateMachineState::SendRequestVersionResponse); interfaceUnderTest.update(); EXPECT_EQ(interfaceUnderTest.test_wrapper_get_state(), TaskControllerClient::StateMachineState::Disconnected); + + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + ASSERT_TRUE(tcPartner->destroy(3)); + ASSERT_TRUE(internalECU->destroy(4)); } TEST(TASK_CONTROLLER_CLIENT_TESTS, WorkerThread) @@ -1345,18 +1360,19 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, WorkerThread) clientNAME.set_industry_group(2); clientNAME.set_ecu_instance(1); clientNAME.set_function_code(static_cast(NAME::Function::RateControl)); - auto internalECU = std::make_shared(clientNAME, 0x85, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x85, 0); std::vector vtNameFilters; const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::TaskController)); vtNameFilters.push_back(testFilter); - auto vtPartner = std::make_shared(0, vtNameFilters); + auto tcPartner = PartneredControlFunction::create(0, vtNameFilters); - DerivedTestTCClient interfaceUnderTest(vtPartner, internalECU); + DerivedTestTCClient interfaceUnderTest(tcPartner, internalECU); EXPECT_NO_THROW(interfaceUnderTest.initialize(true)); EXPECT_NO_THROW(interfaceUnderTest.terminate()); + ASSERT_TRUE(tcPartner->destroy(3)); // Account for the pointer in the TC client and the language interface } static bool valueRequested = false; @@ -1403,15 +1419,22 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, CallbackTests) clientNAME.set_industry_group(2); clientNAME.set_ecu_instance(1); clientNAME.set_function_code(static_cast(NAME::Function::RateControl)); - auto internalECU = std::make_shared(clientNAME, 0x86, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x86, 0); const isobus::NAMEFilter filterTaskController(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::TaskController)); const std::vector tcNameFilters = { filterTaskController }; - std::shared_ptr TestPartnerTC = std::make_shared(0, tcNameFilters); + std::shared_ptr TestPartnerTC = isobus::PartneredControlFunction::create(0, tcNameFilters); auto blankDDOP = std::make_shared(); - CANMessageFrame testFrame; + std::uint32_t waitingTimestamp_ms = SystemTiming::get_timestamp_ms(); + + while ((!internalECU->get_address_valid()) && + (!SystemTiming::time_expired_ms(waitingTimestamp_ms, 2000))) + { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } // Force claim a partner + CANMessageFrame testFrame; testFrame.dataLength = 8; testFrame.channel = 0; testFrame.isExtendedFrame = true; @@ -1424,15 +1447,6 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, CallbackTests) testFrame.data[5] = 0x82; testFrame.data[6] = 0x00; testFrame.data[7] = 0xA0; - - std::uint32_t waitingTimestamp_ms = SystemTiming::get_timestamp_ms(); - - while ((!internalECU->get_address_valid()) && - (!SystemTiming::time_expired_ms(waitingTimestamp_ms, 2000))) - { - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - } - CANNetworkManager::process_receive_can_message_frame(testFrame); DerivedTestTCClient interfaceUnderTest(TestPartnerTC, internalECU); @@ -1684,4 +1698,8 @@ TEST(TASK_CONTROLLER_CLIENT_TESTS, CallbackTests) EXPECT_EQ(requestedDDI, 0x3B19); CANHardwareInterface::stop(); + + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + ASSERT_TRUE(TestPartnerTC->destroy(3)); + // ASSERT_TRUE(internalECU->destroy(4)); } diff --git a/test/vt_client_tests.cpp b/test/vt_client_tests.cpp index 41ee3c71..4e85057b 100644 --- a/test/vt_client_tests.cpp +++ b/test/vt_client_tests.cpp @@ -90,13 +90,13 @@ std::vector DerivedTestVTClient::staticTestPool; TEST(VIRTUAL_TERMINAL_TESTS, InitializeAndInitialState) { NAME clientNAME(0); - auto internalECU = std::make_shared(clientNAME, 0x26, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x26, 0); std::vector vtNameFilters; const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::VirtualTerminal)); vtNameFilters.push_back(testFilter); - auto vtPartner = std::make_shared(0, vtNameFilters); + auto vtPartner = PartneredControlFunction::create(0, vtNameFilters); DerivedTestVTClient clientUnderTest(vtPartner, internalECU); @@ -124,18 +124,20 @@ TEST(VIRTUAL_TERMINAL_TESTS, InitializeAndInitialState) EXPECT_NE(nullptr, clientUnderTest.get_partner_control_function()); clientUnderTest.terminate(); + ASSERT_TRUE(vtPartner->destroy(3)); + ASSERT_TRUE(internalECU->destroy(4)); } TEST(VIRTUAL_TERMINAL_TESTS, VTStatusMessage) { NAME clientNAME(0); - auto internalECU = std::make_shared(clientNAME, 0x26, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x26, 0); std::vector vtNameFilters; const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::VirtualTerminal)); vtNameFilters.push_back(testFilter); - auto vtPartner = std::make_shared(0, vtNameFilters); + auto vtPartner = PartneredControlFunction::create(0, vtNameFilters); DerivedTestVTClient clientUnderTest(vtPartner, internalECU); @@ -167,6 +169,10 @@ TEST(VIRTUAL_TERMINAL_TESTS, VTStatusMessage) // Test the master address is correct when in the connected state clientUnderTest.test_wrapper_set_state(VirtualTerminalClient::StateMachineState::Connected); EXPECT_EQ(0x26, clientUnderTest.get_active_working_set_master_address()); + + // expectedRefCount=3 is to account for the pointer in the VT client and the language interface + ASSERT_TRUE(vtPartner->destroy(3)); + ASSERT_TRUE(internalECU->destroy(3)); } TEST(VIRTUAL_TERMINAL_TESTS, FullPoolAutoscalingWithVector) @@ -182,13 +188,13 @@ TEST(VIRTUAL_TERMINAL_TESTS, FullPoolAutoscalingWithVector) clientNAME.set_device_class_instance(0); clientNAME.set_manufacturer_code(69); - auto internalECU = std::make_shared(clientNAME, 0x26, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x26, 0); std::vector vtNameFilters; const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::VirtualTerminal)); vtNameFilters.push_back(testFilter); - auto vtPartner = std::make_shared(0, vtNameFilters); + auto vtPartner = PartneredControlFunction::create(0, vtNameFilters); DerivedTestVTClient clientUnderTest(vtPartner, internalECU); @@ -219,6 +225,10 @@ TEST(VIRTUAL_TERMINAL_TESTS, FullPoolAutoscalingWithVector) // Full scaling test using the example pool EXPECT_EQ(true, clientUnderTest.test_wrapper_scale_object_pools()); + + // expectedRefCount=3 is to account for the pointer in the VT client and the language interface + ASSERT_TRUE(vtPartner->destroy(3)); + ASSERT_TRUE(internalECU->destroy(3)); } TEST(VIRTUAL_TERMINAL_TESTS, FullPoolAutoscalingWithDataChunkCallbacks) @@ -234,13 +244,13 @@ TEST(VIRTUAL_TERMINAL_TESTS, FullPoolAutoscalingWithDataChunkCallbacks) clientNAME.set_device_class_instance(0); clientNAME.set_manufacturer_code(69); - auto internalECU = std::make_shared(clientNAME, 0x26, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x26, 0); std::vector vtNameFilters; const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::VirtualTerminal)); vtNameFilters.push_back(testFilter); - auto vtPartner = std::make_shared(0, vtNameFilters); + auto vtPartner = PartneredControlFunction::create(0, vtNameFilters); DerivedTestVTClient clientUnderTest(vtPartner, internalECU); @@ -264,6 +274,10 @@ TEST(VIRTUAL_TERMINAL_TESTS, FullPoolAutoscalingWithDataChunkCallbacks) // Full scaling test using the example pool EXPECT_EQ(true, clientUnderTest.test_wrapper_scale_object_pools()); + + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + ASSERT_TRUE(vtPartner->destroy(3)); + ASSERT_TRUE(internalECU->destroy(3)); } TEST(VIRTUAL_TERMINAL_TESTS, FullPoolAutoscalingWithPointer) @@ -279,13 +293,13 @@ TEST(VIRTUAL_TERMINAL_TESTS, FullPoolAutoscalingWithPointer) clientNAME.set_device_class_instance(0); clientNAME.set_manufacturer_code(69); - auto internalECU = std::make_shared(clientNAME, 0x26, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x26, 0); std::vector vtNameFilters; const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::VirtualTerminal)); vtNameFilters.push_back(testFilter); - auto vtPartner = std::make_shared(0, vtNameFilters); + auto vtPartner = PartneredControlFunction::create(0, vtNameFilters); DerivedTestVTClient clientUnderTest(vtPartner, internalECU); @@ -321,18 +335,22 @@ TEST(VIRTUAL_TERMINAL_TESTS, FullPoolAutoscalingWithPointer) // Full scaling test using the example pool EXPECT_EQ(true, clientUnderTest.test_wrapper_scale_object_pools()); + + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + ASSERT_TRUE(vtPartner->destroy(3)); + ASSERT_TRUE(internalECU->destroy(3)); } TEST(VIRTUAL_TERMINAL_TESTS, ObjectMetadataTests) { NAME clientNAME(0); - auto internalECU = std::make_shared(clientNAME, 0x26, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x26, 0); std::vector vtNameFilters; const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::VirtualTerminal)); vtNameFilters.push_back(testFilter); - auto vtPartner = std::make_shared(0, vtNameFilters); + auto vtPartner = PartneredControlFunction::create(0, vtNameFilters); DerivedTestVTClient clientUnderTest(vtPartner, internalECU); @@ -380,6 +398,10 @@ TEST(VIRTUAL_TERMINAL_TESTS, ObjectMetadataTests) // Don't support proprietary objects for autoscaling EXPECT_EQ(0, clientUnderTest.test_wrapper_get_minimum_object_length(VirtualTerminalObjectType::ManufacturerDefined11)); + + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + ASSERT_TRUE(vtPartner->destroy(3)); + ASSERT_TRUE(internalECU->destroy(3)); } TEST(VIRTUAL_TERMINAL_TESTS, FontRemapping) @@ -824,7 +846,7 @@ TEST(VIRTUAL_TERMINAL_TESTS, MessageConstruction) clientNAME.set_function_code(6); clientNAME.set_identity_number(975); clientNAME.set_function_code(static_cast(NAME::Function::ControlHead)); - auto internalECU = std::make_shared(clientNAME, 0x37, 0); + auto internalECU = InternalControlFunction::create(clientNAME, 0x37, 0); CANMessageFrame testFrame; @@ -842,7 +864,7 @@ TEST(VIRTUAL_TERMINAL_TESTS, MessageConstruction) const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::VirtualTerminal)); vtNameFilters.push_back(testFilter); - auto vtPartner = std::make_shared(0, vtNameFilters); + auto vtPartner = PartneredControlFunction::create(0, vtNameFilters); // Force claim a partner NAME serverNAME(0); @@ -877,6 +899,7 @@ TEST(VIRTUAL_TERMINAL_TESTS, MessageConstruction) serverVT.read_frame(testFrame); } ASSERT_TRUE(serverVT.get_queue_empty()); + EXPECT_TRUE(vtPartner->get_address_valid()); // Test Change active mask interfaceUnderTest.send_change_active_mask(123, 456); @@ -969,4 +992,8 @@ TEST(VIRTUAL_TERMINAL_TESTS, MessageConstruction) serverVT.close(); CANHardwareInterface::stop(); + + // expectedRefCount=3 is to account for the pointer in the VT client and the language interface + ASSERT_TRUE(vtPartner->destroy(3)); + ASSERT_TRUE(internalECU->destroy(3)); }