From 41c51d99bc8b30ed907039972bbc074ae3b3e29d Mon Sep 17 00:00:00 2001 From: Daan Steenbergen Date: Mon, 19 Jun 2023 23:22:26 +0200 Subject: [PATCH] [Core]: Switch to smart pointers for CFs With this change all the current raw pointers are converted to smart pointers, e.g. `shared_ptr` --- examples/diagnostic_protocol/main.cpp | 2 +- examples/nmea2000/main.cpp | 8 +- examples/pgn_requests/main.cpp | 12 +- examples/task_controller_client/main.cpp | 4 +- examples/transport_layer/main.cpp | 14 +- .../virtual_terminal/aux_functions/main.cpp | 4 +- examples/virtual_terminal/aux_inputs/main.cpp | 4 +- .../version3_object_pool/main.cpp | 4 +- .../include/isobus/isobus/can_callbacks.hpp | 14 +- .../isobus/isobus/can_control_function.hpp | 32 +- .../can_extended_transport_protocol.hpp | 10 +- .../isobus/can_internal_control_function.hpp | 22 +- isobus/include/isobus/isobus/can_message.hpp | 12 +- .../isobus/isobus/can_network_manager.hpp | 57 +-- ...arameter_group_number_request_protocol.hpp | 10 +- .../isobus/can_partnered_control_function.hpp | 31 +- isobus/include/isobus/isobus/can_protocol.hpp | 4 +- .../isobus/isobus/can_transport_protocol.hpp | 10 +- .../isobus/isobus_diagnostic_protocol.hpp | 14 +- .../isobus/isobus/isobus_functionalities.hpp | 2 +- .../isobus/isobus_guidance_interface.hpp | 22 +- .../isobus_maintain_power_interface.hpp | 6 +- .../isobus/isobus_speed_distance_messages.hpp | 24 +- .../isobus/isobus_task_controller_client.hpp | 4 +- .../isobus/isobus_virtual_terminal_client.hpp | 4 +- .../isobus/nmea2000_fast_packet_protocol.hpp | 14 +- .../src/can_address_claim_state_machine.cpp | 4 +- isobus/src/can_callbacks.cpp | 4 +- isobus/src/can_control_function.cpp | 32 +- .../src/can_extended_transport_protocol.cpp | 40 +- isobus/src/can_internal_control_function.cpp | 42 +- isobus/src/can_message.cpp | 8 +- isobus/src/can_network_manager.cpp | 420 ++++++++---------- ...arameter_group_number_request_protocol.cpp | 16 +- isobus/src/can_partnered_control_function.cpp | 57 +-- isobus/src/can_transport_protocol.cpp | 38 +- isobus/src/isobus_diagnostic_protocol.cpp | 32 +- isobus/src/isobus_functionalities.cpp | 4 +- isobus/src/isobus_guidance_interface.cpp | 21 +- .../src/isobus_language_command_interface.cpp | 2 +- .../src/isobus_maintain_power_interface.cpp | 8 +- .../src/isobus_shortcut_button_interface.cpp | 2 +- isobus/src/isobus_speed_distance_messages.cpp | 32 +- isobus/src/isobus_task_controller_client.cpp | 40 +- isobus/src/isobus_virtual_terminal_client.cpp | 312 ++++++------- isobus/src/nmea2000_fast_packet_protocol.cpp | 18 +- .../source/Tutorials/Adding a Destination.rst | 6 +- sphinx/source/Tutorials/PGN Requests.rst | 4 +- .../source/Tutorials/Receiving Messages.rst | 4 +- .../Tutorials/The ISOBUS Hello World.rst | 8 +- .../Tutorials/Virtual Terminal Basics.rst | 8 +- test/address_claim_tests.cpp | 23 +- test/cf_functionalities_tests.cpp | 20 +- test/core_network_management_tests.cpp | 37 +- test/diagnostic_protocol_tests.cpp | 5 +- test/guidance_tests.cpp | 4 +- test/isb_tests.cpp | 10 +- test/language_command_interface_tests.cpp | 18 +- test/maintain_power_tests.cpp | 17 +- test/speed_distance_message_tests.cpp | 4 +- test/tc_client_tests.cpp | 81 ++-- test/vt_client_tests.cpp | 55 ++- 62 files changed, 938 insertions(+), 842 deletions(-) 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 f1521e16..5e5e45a6 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,14 +67,24 @@ 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 = Type::External; ///< 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 bool claimedAddressSinceLastAddressClaimRequest = false; ///< Used to mark CFs as stale if they don't claim within a certain time + std::uint8_t address; ///< The address 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 15282066..7a3d2c1c 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 = false; ///< 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 f06cd9b6..a57e69f8 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 @@ -198,10 +204,8 @@ namespace isobus /// @param[in] message A message being received by the stack 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] claimedAddress The address claimed - void update_address_table(std::uint8_t CANPort, std::uint8_t claimedAddress); + /// @brief Updates the internal address table based on updates to internal cfs addresses + void update_internal_cfs(); /// @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 +240,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. @@ -308,9 +312,10 @@ 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 lastAddressClaimRequestTimestamp_ms; ///< Stores timestamps for when the last request for the address claim PGN was recieved. Used to prune stale CFs. - std::array, CAN_PORT_MAXIMUM> controlFunctionTable; ///< Table to maintain address to NAME mappings - std::list 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::list> 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 28d3ad95..6fc6a923 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_maintain_power_interface.hpp b/isobus/include/isobus/isobus/isobus_maintain_power_interface.hpp index 78e5bdbf..b65f95f2 100644 --- a/isobus/include/isobus/isobus/isobus_maintain_power_interface.hpp +++ b/isobus/include/isobus/isobus/isobus_maintain_power_interface.hpp @@ -94,7 +94,7 @@ namespace isobus }; /// @brief Constructor for a MaintainPowerData object, which stores information sent/received in a maintain power message. - explicit MaintainPowerData(ControlFunction *sendingControlFunction); + explicit MaintainPowerData(std::shared_ptr sendingControlFunction); /// @brief Sets the reported implement in-work state /// @param[in] inWorkState The reported implement in-work state to set @@ -157,7 +157,7 @@ namespace isobus /// 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 @@ -169,7 +169,7 @@ namespace isobus private: MaintainPowerData() = delete; - ControlFunction *sendingControlFunction = nullptr; ///< The control function that is sending the message. + std::shared_ptr sendingControlFunction = nullptr; ///< The control function that is sending the message. std::uint32_t timestamp_ms = 0; ///< A timestamp for when the message was released in milliseconds ImplementInWorkState currentImplementInWorkState = ImplementInWorkState::NotAvailable; ///< The reported implement in-work state ImplementReadyToWorkState currentImplementReadyToWorkState = ImplementReadyToWorkState::NotAvailable; ///< The reported implement ready to work state diff --git a/isobus/include/isobus/isobus/isobus_speed_distance_messages.hpp b/isobus/include/isobus/isobus/isobus_speed_distance_messages.hpp index 5c6f5b59..6c809229 100644 --- a/isobus/include/isobus/isobus/isobus_speed_distance_messages.hpp +++ b/isobus/include/isobus/isobus/isobus_speed_distance_messages.hpp @@ -85,7 +85,7 @@ namespace isobus /// @brief Constructor for a WheelBasedMachineSpeedData /// @param[in] sender The control function that is sending this message - explicit WheelBasedMachineSpeedData(ControlFunction *sender); + explicit WheelBasedMachineSpeedData(std::shared_ptr sender); /// @brief Returns The distance traveled by a machine as calculated from wheel or tail-shaft speed. /// @note When the distance exceeds 4211081215m the value shall be reset to zero and incremented as additional distance accrues. @@ -166,7 +166,7 @@ namespace isobus /// 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 @@ -177,7 +177,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 std::uint32_t timestamp_ms = 0; ///< A timestamp for when the message was released in milliseconds std::uint32_t wheelBasedMachineDistance_mm = 0; ///< Stores the decoded machine wheel-based distance in millimeters std::uint16_t wheelBasedMachineSpeed_mm_per_sec = 0; ///< Stores the decoded wheel-based machine speed in mm/s @@ -247,7 +247,7 @@ namespace isobus /// @brief Constructor for a MachineSelectedSpeedData /// @param[in] sender The control function that is sending this message - explicit MachineSelectedSpeedData(ControlFunction *sender); + explicit MachineSelectedSpeedData(std::shared_ptr sender); /// @brief Returns the Actual distance travelled by the machine based on the value of selected machine speed (SPN 4305). /// @note When the distance exceeds 4211081215 meters the value shall be reset to zero and incremented as additional distance accrues. @@ -319,7 +319,7 @@ namespace isobus /// 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 @@ -330,7 +330,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 std::uint32_t timestamp_ms = 0; ///< A timestamp for when the message was released in milliseconds std::uint32_t machineSelectedSpeedDistance_mm = 0; ///< Stores the machine selected speed distance in millimeters std::uint16_t machineSelectedSpeed_mm_per_sec = 0; ///< Stores the machine selected speed in mm/s @@ -351,7 +351,7 @@ namespace isobus public: /// @brief Constructor for a GroundBasedSpeedData /// @param[in] sender The control function that is sending this message - explicit GroundBasedSpeedData(ControlFunction *sender); + explicit GroundBasedSpeedData(std::shared_ptr sender); /// @brief Actual distance traveled by a machine, based on measurements from a sensor such as that is not susceptible to wheel slip /// (e.g. radar, GPS, LIDAR, or stationary object tracking) @@ -395,7 +395,7 @@ namespace isobus /// 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 @@ -406,7 +406,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 std::uint32_t timestamp_ms = 0; ///< A timestamp for when the message was released in milliseconds std::uint32_t groundBasedMachineDistance_mm = 0; ///< Stores the ground-based speed's distance in millimeters std::uint16_t groundBasedMachineSpeed_mm_per_sec = 0; ///< Stores the ground-based speed in mm/s @@ -422,7 +422,7 @@ namespace isobus public: /// @brief Constructor for a MachineSelectedSpeedCommandData /// @param[in] sender The control function that is sending this message - explicit MachineSelectedSpeedCommandData(ControlFunction *sender); + explicit MachineSelectedSpeedCommandData(std::shared_ptr sender); /// @brief Returns the commanded setpoint value of the machine speed as measured by the selected source in mm/s /// @return The commanded setpoint value of the machine speed as measured by the selected source in mm/s @@ -459,7 +459,7 @@ namespace isobus /// 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 @@ -470,7 +470,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 std::uint32_t timestamp_ms = 0; ///< A timestamp for when the message was released in milliseconds std::uint16_t speedCommandedSetpoint = 0; ///< Stores the commanded speed setpoint in mm/s std::uint16_t speedSetpointLimit = 0; ///< Stores the maximum allowed speed in mm/s 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 006faac9..9b898fc3 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 dd25ad63..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,21 +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), 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 @@ -52,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 cd1dad30..04610007 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,44 +16,35 @@ 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) { - 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 3abca56e..a78fc070 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 //================================================================================================ @@ -36,16 +37,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; } } @@ -86,14 +87,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; } @@ -116,8 +117,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, @@ -206,25 +207,7 @@ namespace isobus InternalControlFunction::update_address_claiming({}); - if (InternalControlFunction::get_any_internal_control_function_changed_address({})) - { - for (std::size_t i = 0; i < InternalControlFunction::get_number_internal_control_functions(); i++) - { - InternalControlFunction *currentInternalControlFunction = InternalControlFunction::get_internal_control_function(i); - - if (nullptr != currentInternalControlFunction) - { - if (activeControlFunctions.end() == std::find(activeControlFunctions.begin(), activeControlFunctions.end(), currentInternalControlFunction)) - { - activeControlFunctions.push_back(currentInternalControlFunction); - } - if (currentInternalControlFunction->get_changed_address_since_last_update({})) - { - update_address_table(currentInternalControlFunction->get_can_port(), currentInternalControlFunction->get_address()); - } - } - } - } + update_internal_cfs(); prune_inactive_control_functions(); @@ -291,28 +274,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 (auto i = CANNetworkManager::CANNetwork.activeControlFunctions.begin(); i != CANNetworkManager::CANNetwork.activeControlFunctions.end(); i++) - { - if (((*i)->get_can_port() == tempCANMessage.get_can_port_index()) && - ((*i)->get_address() == tempCANMessage.get_identifier().get_source_address())) - { - tempCANMessage.set_source_control_function(*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()); @@ -325,37 +288,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 incorrect 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, 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() @@ -408,105 +375,111 @@ namespace isobus void CANNetworkManager::update_address_table(const CANMessage &message) { - std::uint8_t CANPort = message.get_can_port_index(); + std::uint8_t channelIndex = message.get_can_port_index(); if ((static_cast(CANLibParameterGroupNumber::AddressClaim) == message.get_identifier().get_parameter_group_number()) && - (CANPort < CAN_PORT_MAXIMUM)) + (channelIndex < CAN_PORT_MAXIMUM)) { - std::uint8_t messageSourceAddress = message.get_identifier().get_source_address(); - - if ((nullptr != controlFunctionTable[CANPort][messageSourceAddress]) && - (CANIdentifier::NULL_ADDRESS == controlFunctionTable[CANPort][messageSourceAddress]->get_address())) + std::uint8_t claimedAddress = message.get_identifier().get_source_address(); + auto targetControlFunction = controlFunctionTable[channelIndex][claimedAddress]; + if ((nullptr != targetControlFunction) && + (CANIdentifier::NULL_ADDRESS == targetControlFunction->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 + targetControlFunction->address = NULL_CAN_ADDRESS; + inactiveControlFunctions.push_back(targetControlFunction); + targetControlFunction = nullptr; + CANStackLogger::debug("[NM]: %s CF '%016llx' is evicted from address '%d' on channel '%d', as their address is probably stolen.", + targetControlFunction->get_type_string().c_str(), + targetControlFunction->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 (targetControlFunction != nullptr) + { + targetControlFunction->claimedAddressSinceLastAddressClaimRequest = true; + } + else { - // Look through active CFs, maybe we've heard of this ECU before - for (auto ¤tControlFunction : activeControlFunctions) + // Look through all inactive CFs, maybe one of them has freshly claimed the address + for (auto currentControlFunction : inactiveControlFunctions) { - if (currentControlFunction->get_address() == messageSourceAddress) + if ((currentControlFunction->get_address() == claimedAddress) && + (currentControlFunction->get_can_port() == channelIndex)) { - // Scan the address table to remove this CF from a previous location if needed - for (std::uint_fast8_t i = 0; i < NULL_CAN_ADDRESS; i++) - { - if ((nullptr != controlFunctionTable[CANPort][i]) && - (controlFunctionTable[CANPort][i]->get_NAME() == currentControlFunction->get_NAME()) && - (i != messageSourceAddress)) - { - controlFunctionTable[CANPort][i] = nullptr; - CANStackLogger::debug("[NM]: Detected that CF %016llx on channel %u is moving from address %u to %u.", - currentControlFunction->get_NAME().get_full_name(), - CANPort, - i, - messageSourceAddress); - break; - } - } - - // ECU has claimed since the last update, add it to the table - controlFunctionTable[CANPort][messageSourceAddress] = currentControlFunction; - currentControlFunction->address = messageSourceAddress; - currentControlFunction->claimedAddressSinceLastAddressClaimRequest = true; + controlFunctionTable[channelIndex][claimedAddress] = currentControlFunction; + CANStackLogger::debug("[NM]: %s CF '%016llx' is now active at address '%d' on channel '%d'.", + currentControlFunction->get_type_string().c_str(), + currentControlFunction->get_NAME().get_full_name(), + claimedAddress, + channelIndex); break; } } } - else - { - controlFunctionTable[CANPort][messageSourceAddress]->claimedAddressSinceLastAddressClaimRequest = true; - } } else if ((static_cast(CANLibParameterGroupNumber::ParameterGroupNumberRequest) == message.get_identifier().get_parameter_group_number()) && - (CANPort < CAN_PORT_MAXIMUM)) + (channelIndex < CAN_PORT_MAXIMUM)) { auto requestedPGN = message.get_uint24_at(0); if (static_cast(CANLibParameterGroupNumber::AddressClaim) == requestedPGN) { - lastAddressClaimRequestTimestamp_ms.at(CANPort) = SystemTiming::get_timestamp_ms(); + lastAddressClaimRequestTimestamp_ms.at(channelIndex) = SystemTiming::get_timestamp_ms(); - for (auto &activeControlFunction : activeControlFunctions) + // Reset the claimedAddressSinceLastAddressClaimRequest flag for all control functions on the port + auto result = std::find_if(inactiveControlFunctions.begin(), inactiveControlFunctions.end(), [channelIndex](std::shared_ptr controlFunction) { + return (channelIndex == controlFunction->get_can_port()); + }); + if (result != inactiveControlFunctions.end()) { - if (CANPort == activeControlFunction->get_can_port()) + (*result)->claimedAddressSinceLastAddressClaimRequest = true; + } + std::for_each(controlFunctionTable[channelIndex].begin(), controlFunctionTable[channelIndex].end(), [](std::shared_ptr controlFunction) { + if (nullptr != controlFunction) { - activeControlFunction->claimedAddressSinceLastAddressClaimRequest = false; + controlFunction->claimedAddressSinceLastAddressClaimRequest = false; } - } + }); } } } - void CANNetworkManager::update_address_table(std::uint8_t CANPort, std::uint8_t claimedAddress) + void CANNetworkManager::update_internal_cfs() { - if (CANPort < CAN_PORT_MAXIMUM) + if (InternalControlFunction::get_any_internal_control_function_changed_address({})) { - if (nullptr != controlFunctionTable[CANPort][claimedAddress]) + for (std::size_t i = 0; i < InternalControlFunction::get_number_internal_control_functions(); i++) { - // Someone is at that spot in the table, but their address was stolen by an internal control function - // Need to evict them from the table - controlFunctionTable[CANPort][claimedAddress]->address = NULL_CAN_ADDRESS; - controlFunctionTable[CANPort][claimedAddress] = nullptr; - } + std::shared_ptr currentInternalControlFunction = InternalControlFunction::get_internal_control_function(i); - // 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) + if (nullptr != currentInternalControlFunction && currentInternalControlFunction->get_changed_address_since_last_update({})) { - if (currentControlFunction->get_address() == claimedAddress) + std::uint8_t channelIndex = currentInternalControlFunction->get_can_port(); + std::uint8_t claimedAddress = currentInternalControlFunction->get_address(); + + // Check if the internal control function switched addresses, and therefore needs to be moved in the table + for (std::uint8_t address = 0; address < NULL_CAN_ADDRESS; address++) { - // ECU has claimed since the last update, add it to the table - controlFunctionTable[CANPort][claimedAddress] = currentControlFunction; - currentControlFunction->address = claimedAddress; - break; + if (controlFunctionTable[channelIndex][address] == currentInternalControlFunction) + { + controlFunctionTable[channelIndex][address] = nullptr; + break; + } } + + if (nullptr != controlFunctionTable[channelIndex][claimedAddress]) + { + // Someone is at that spot in the table, but their address was stolen by an internal control function + // Need to evict them from the table + controlFunctionTable[channelIndex][claimedAddress]->address = NULL_CAN_ADDRESS; + controlFunctionTable[channelIndex][claimedAddress] = nullptr; + } + + // ECU has claimed since the last update, add it to the table + controlFunctionTable[channelIndex][claimedAddress] = currentInternalControlFunction; } } } @@ -546,7 +519,8 @@ namespace isobus (rxFrame.channel < CAN_PORT_MAXIMUM)) { std::uint64_t claimedNAME; - ControlFunction *foundControlFunction = nullptr; + std::shared_ptr foundControlFunction = nullptr; + uint8_t claimedAddress = CANIdentifier(rxFrame.identifier).get_source_address(); claimedNAME = rxFrame.data[0]; claimedNAME |= (static_cast(rxFrame.data[1]) << 8); @@ -557,38 +531,26 @@ namespace isobus claimedNAME |= (static_cast(rxFrame.data[6]) << 48); claimedNAME |= (static_cast(rxFrame.data[7]) << 56); - for (auto i = activeControlFunctions.begin(); i != activeControlFunctions.end(); 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 == (*i)->controlFunctionNAME.get_full_name()) && - (rxFrame.channel == (*i)->get_can_port())) - { - // Device already in the active list - foundControlFunction = (*i); - break; - } - else if (((*i)->address == CANIdentifier(rxFrame.identifier).get_source_address()) && - (rxFrame.channel == (*i)->get_can_port())) - { - // If this CF has the same address as the one claiming, we need set it to 0xFE (null address) - (*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; } } @@ -601,26 +563,58 @@ namespace isobus (PartneredControlFunction::partneredControlFunctionList[i]->get_can_port() == rxFrame.channel) && (PartneredControlFunction::partneredControlFunctionList[i]->check_matches_name(NAME(claimedNAME)))) { - PartneredControlFunction::partneredControlFunctionList[i]->address = CANIdentifier(rxFrame.identifier).get_source_address(); + PartneredControlFunction::partneredControlFunctionList[i]->address = claimedAddress; 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()))); - } } - if (nullptr != foundControlFunction) + // Remove any CF that has the same address as the one claiming + std::for_each(controlFunctionTable[rxFrame.channel].begin(), + controlFunctionTable[rxFrame.channel].end(), + [&foundControlFunction, &claimedAddress](const std::shared_ptr &cf) { + if ((nullptr != cf) && (foundControlFunction != cf) && (cf->address == claimedAddress)) + cf->address = CANIdentifier::NULL_ADDRESS; + }); + + std::for_each(inactiveControlFunctions.begin(), + inactiveControlFunctions.end(), + [&rxFrame, &foundControlFunction, &claimedAddress](const std::shared_ptr &cf) { + if ((foundControlFunction != cf) && (cf->address == claimedAddress) && (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), claimedAddress, rxFrame.channel); + controlFunctionTable[rxFrame.channel][foundControlFunction->get_address()] = foundControlFunction; + CANStackLogger::debug("[NM]: New Control function %d", foundControlFunction->get_address()); + } + else { - foundControlFunction->address = CANIdentifier(rxFrame.identifier).get_source_address(); + if (foundControlFunction->address != claimedAddress) + { + if (foundControlFunction->get_address_valid()) + { + controlFunctionTable[rxFrame.channel][claimedAddress] = foundControlFunction; + controlFunctionTable[rxFrame.channel][foundControlFunction->get_address()] = nullptr; + CANStackLogger::info("[NM]: The %s control function at address %d changed it's address to %d.", + foundControlFunction->get_type_string().c_str(), + foundControlFunction->get_address(), + claimedAddress); + } + else + { + CANStackLogger::debug("[NM]: A %s control function claimed '%d'.", + foundControlFunction->get_type_string().c_str(), + claimedAddress); + } + foundControlFunction->address = claimedAddress; + } } } } @@ -629,7 +623,7 @@ namespace isobus { if (PartneredControlFunction::anyPartnerNeedsInitializing) { - for (auto &partner : PartneredControlFunction::partneredControlFunctionList) + for (const auto &partner : PartneredControlFunction::partneredControlFunctionList) { if ((nullptr != partner) && (!partner->initialized)) { @@ -658,10 +652,10 @@ 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())) && - (partner->get_can_port() == (*currentActiveControlFunction)->get_can_port()) && + if ((nullptr != (*currentActiveControlFunction)) && + (partner->check_matches_name((*currentActiveControlFunction)->get_NAME())) && (ControlFunction::Type::External == (*currentActiveControlFunction)->get_type())) { // This CF matches the filter and is not an internal or already partnered CF @@ -671,9 +665,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; } } @@ -745,13 +737,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; } @@ -798,7 +790,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()) && @@ -825,7 +817,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())) @@ -893,44 +885,26 @@ namespace isobus void CANNetworkManager::prune_inactive_control_functions() { - for (std::uint_fast8_t i = 0; i < CAN_PORT_MAXIMUM; i++) + for (std::uint_fast8_t channelIndex = 0; channelIndex < CAN_PORT_MAXIMUM; channelIndex++) { constexpr std::uint32_t MAX_ADDRESS_CLAIM_RESOLUTION_TIME = 755; // This is 250ms + RTxD + 250ms - if ((0 != lastAddressClaimRequestTimestamp_ms.at(i)) && - (SystemTiming::time_expired_ms(lastAddressClaimRequestTimestamp_ms.at(i), MAX_ADDRESS_CLAIM_RESOLUTION_TIME))) + if ((0 != lastAddressClaimRequestTimestamp_ms.at(channelIndex)) && + (SystemTiming::time_expired_ms(lastAddressClaimRequestTimestamp_ms.at(channelIndex), MAX_ADDRESS_CLAIM_RESOLUTION_TIME))) { - for (auto activeCF = activeControlFunctions.begin(); activeCF != activeControlFunctions.end(); activeCF++) + for (std::uint_fast8_t i = 0; i < NULL_CAN_ADDRESS; i++) { - if ((nullptr != (*activeCF)) && - ((*activeCF)->canPortIndex == i) && - (!(*activeCF)->claimedAddressSinceLastAddressClaimRequest) && - (ControlFunction::Type::Internal != (*activeCF)->get_type())) + auto controlFunction = controlFunctionTable[channelIndex][i]; + if ((nullptr != controlFunction) && + (!controlFunction->claimedAddressSinceLastAddressClaimRequest) && + (ControlFunction::Type::Internal != controlFunction->get_type())) { - ControlFunction *cfToMove = (*activeCF); - activeCF = activeControlFunctions.erase(activeCF); - - if (activeControlFunctions.begin() != activeCF) - { - activeCF--; - } - - inactiveControlFunctions.push_back(cfToMove); - assert(nullptr != cfToMove); - - if ((NULL_CAN_ADDRESS != cfToMove->get_address()) && - (nullptr != controlFunctionTable.at(i).at(cfToMove->get_address()))) - { - CANStackLogger::debug("[NM]: Control function on channel %u with address %u and NAME %016llx is now offline.", i, cfToMove->get_address(), cfToMove->get_NAME()); - controlFunctionTable.at(i).at(cfToMove->get_address()) = nullptr; - cfToMove->address = NULL_CAN_ADDRESS; - } - if (activeControlFunctions.end() == activeCF) - { - break; - } + inactiveControlFunctions.push_back(controlFunction); + CANStackLogger::debug("[NM]: Control function on channel %u with address %u and NAME %016llx is now offline.", channelIndex, controlFunction->get_address(), controlFunction->get_NAME()); + controlFunctionTable[channelIndex][i] = nullptr; + controlFunction->address = NULL_CAN_ADDRESS; } } - lastAddressClaimRequestTimestamp_ms.at(i) = 0; + lastAddressClaimRequestTimestamp_ms.at(channelIndex) = 0; } } } 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 ee71a7ce..062dafa5 100644 --- a/isobus/src/isobus_language_command_interface.cpp +++ b/isobus/src/isobus_language_command_interface.cpp @@ -85,7 +85,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_maintain_power_interface.cpp b/isobus/src/isobus_maintain_power_interface.cpp index 00daaa1b..8085caa0 100644 --- a/isobus/src/isobus_maintain_power_interface.cpp +++ b/isobus/src/isobus_maintain_power_interface.cpp @@ -11,7 +11,7 @@ namespace isobus { MaintainPowerInterface::MaintainPowerInterface(std::shared_ptr sourceControlFunction) : - maintainPowerTransmitData(sourceControlFunction.get()), + maintainPowerTransmitData(sourceControlFunction), txFlags(static_cast(TransmitFlags::NumberOfFlags), process_flags, this) { } @@ -61,7 +61,7 @@ namespace isobus } } - MaintainPowerInterface::MaintainPowerData::MaintainPowerData(ControlFunction *sendingControlFunction) : + MaintainPowerInterface::MaintainPowerData::MaintainPowerData(std::shared_ptr sendingControlFunction) : sendingControlFunction(sendingControlFunction) { } @@ -138,7 +138,7 @@ namespace isobus return currentMaintainECUPowerState; } - ControlFunction *MaintainPowerInterface::MaintainPowerData::get_sender_control_function() const + std::shared_ptr MaintainPowerInterface::MaintainPowerData::get_sender_control_function() const { return sendingControlFunction; } @@ -213,7 +213,7 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::MaintainPower), buffer.data(), buffer.size(), - static_cast(maintainPowerTransmitData.get_sender_control_function())); + std::dynamic_pointer_cast(maintainPowerTransmitData.get_sender_control_function())); } void MaintainPowerInterface::process_flags(std::uint32_t flag, void *parentPointer) 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_speed_distance_messages.cpp b/isobus/src/isobus_speed_distance_messages.cpp index 46bee63f..7e8d0c6c 100644 --- a/isobus/src/isobus_speed_distance_messages.cpp +++ b/isobus/src/isobus_speed_distance_messages.cpp @@ -33,10 +33,10 @@ namespace isobus bool enableSendingWheelBasedSpeedPeriodically, bool enableSendingMachineSelectedSpeedPeriodically, bool enableSendingMachineSelectedSpeedCommandPeriodically) : - machineSelectedSpeedTransmitData(MachineSelectedSpeedData(enableSendingMachineSelectedSpeedPeriodically ? source.get() : nullptr)), - wheelBasedSpeedTransmitData(WheelBasedMachineSpeedData(enableSendingWheelBasedSpeedPeriodically ? source.get() : nullptr)), - groundBasedSpeedTransmitData(GroundBasedSpeedData(enableSendingGroundBasedSpeedPeriodically ? source.get() : nullptr)), - machineSelectedSpeedCommandTransmitData(MachineSelectedSpeedCommandData(enableSendingMachineSelectedSpeedCommandPeriodically ? source.get() : nullptr)), + machineSelectedSpeedTransmitData(MachineSelectedSpeedData(enableSendingMachineSelectedSpeedPeriodically ? source : nullptr)), + wheelBasedSpeedTransmitData(WheelBasedMachineSpeedData(enableSendingWheelBasedSpeedPeriodically ? source : nullptr)), + groundBasedSpeedTransmitData(GroundBasedSpeedData(enableSendingGroundBasedSpeedPeriodically ? source : nullptr)), + machineSelectedSpeedCommandTransmitData(MachineSelectedSpeedCommandData(enableSendingMachineSelectedSpeedCommandPeriodically ? source : nullptr)), txFlags(static_cast(TransmitFlags::NumberOfFlags), process_flags, this) { } @@ -52,7 +52,7 @@ namespace isobus } } - SpeedMessagesInterface::WheelBasedMachineSpeedData::WheelBasedMachineSpeedData(ControlFunction *sender) : + SpeedMessagesInterface::WheelBasedMachineSpeedData::WheelBasedMachineSpeedData(std::shared_ptr sender) : controlFunction(sender) { } @@ -154,7 +154,7 @@ namespace isobus return retVal; } - ControlFunction *SpeedMessagesInterface::WheelBasedMachineSpeedData::get_sender_control_function() const + std::shared_ptr SpeedMessagesInterface::WheelBasedMachineSpeedData::get_sender_control_function() const { return controlFunction; } @@ -169,7 +169,7 @@ namespace isobus return timestamp_ms; } - SpeedMessagesInterface::MachineSelectedSpeedData::MachineSelectedSpeedData(ControlFunction *sender) : + SpeedMessagesInterface::MachineSelectedSpeedData::MachineSelectedSpeedData(std::shared_ptr sender) : controlFunction(sender) { } @@ -259,7 +259,7 @@ namespace isobus return retVal; } - ControlFunction *SpeedMessagesInterface::MachineSelectedSpeedData::get_sender_control_function() const + std::shared_ptr SpeedMessagesInterface::MachineSelectedSpeedData::get_sender_control_function() const { return controlFunction; } @@ -274,7 +274,7 @@ namespace isobus return timestamp_ms; } - SpeedMessagesInterface::GroundBasedSpeedData::GroundBasedSpeedData(ControlFunction *sender) : + SpeedMessagesInterface::GroundBasedSpeedData::GroundBasedSpeedData(std::shared_ptr sender) : controlFunction(sender) { } @@ -328,7 +328,7 @@ namespace isobus return retVal; } - ControlFunction *SpeedMessagesInterface::GroundBasedSpeedData::get_sender_control_function() const + std::shared_ptr SpeedMessagesInterface::GroundBasedSpeedData::get_sender_control_function() const { return controlFunction; } @@ -343,7 +343,7 @@ namespace isobus return timestamp_ms; } - SpeedMessagesInterface::MachineSelectedSpeedCommandData::MachineSelectedSpeedCommandData(ControlFunction *sender) : + SpeedMessagesInterface::MachineSelectedSpeedCommandData::MachineSelectedSpeedCommandData(std::shared_ptr sender) : controlFunction(sender) { } @@ -398,7 +398,7 @@ namespace isobus return retVal; } - ControlFunction *SpeedMessagesInterface::MachineSelectedSpeedCommandData::get_sender_control_function() const + std::shared_ptr SpeedMessagesInterface::MachineSelectedSpeedCommandData::get_sender_control_function() const { return controlFunction; } @@ -811,7 +811,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::MachineSelectedSpeed), buffer.data(), buffer.size(), - static_cast(machineSelectedSpeedTransmitData.get_sender_control_function()), + std::dynamic_pointer_cast(machineSelectedSpeedTransmitData.get_sender_control_function()), nullptr, CANIdentifier::Priority3); } @@ -838,7 +838,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::WheelBasedSpeedAndDistance), buffer.data(), buffer.size(), - static_cast(wheelBasedSpeedTransmitData.get_sender_control_function()), + std::dynamic_pointer_cast(wheelBasedSpeedTransmitData.get_sender_control_function()), nullptr, CANIdentifier::Priority3); } @@ -862,7 +862,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::GroundBasedSpeedAndDistance), buffer.data(), buffer.size(), - static_cast(groundBasedSpeedTransmitData.get_sender_control_function()), + std::dynamic_pointer_cast(groundBasedSpeedTransmitData.get_sender_control_function()), nullptr, CANIdentifier::Priority3); } @@ -886,7 +886,7 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::MachineSelectedSpeedCommand), buffer.data(), buffer.size(), - static_cast(machineSelectedSpeedCommandTransmitData.get_sender_control_function()), + std::dynamic_pointer_cast(machineSelectedSpeedCommandTransmitData.get_sender_control_function()), nullptr, CANIdentifier::Priority3); } diff --git a/isobus/src/isobus_task_controller_client.cpp b/isobus/src/isobus_task_controller_client.cpp index 9a3a26e0..406f45a0 100644 --- a/isobus/src/isobus_task_controller_client.cpp +++ b/isobus/src/isobus_task_controller_client.cpp @@ -625,8 +625,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, @@ -1693,8 +1693,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) { @@ -1739,8 +1739,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 @@ -1764,8 +1764,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 @@ -1782,8 +1782,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 @@ -1814,8 +1814,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 @@ -1843,8 +1843,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 @@ -1861,8 +1861,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 @@ -1879,8 +1879,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 @@ -1895,7 +1895,7 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::WorkingSetMaster), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), + myControlFunction, nullptr); } @@ -2006,7 +2006,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 1e8385ea..e650dc17 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); } @@ -2557,7 +2557,7 @@ namespace isobus if ((nullptr != parentPointer) && (CAN_DATA_LENGTH <= message.get_data_length()) && ((nullptr == message.get_destination_control_function()) || - (parentVT->myControlFunction.get() == message.get_destination_control_function()))) + (parentVT->myControlFunction == message.get_destination_control_function()))) { switch (message.get_identifier().get_parameter_group_number()) { @@ -3335,8 +3335,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/PGN Requests.rst b/sphinx/source/Tutorials/PGN Requests.rst index ee8afb79..50466e49 100644 --- a/sphinx/source/Tutorials/PGN Requests.rst +++ b/sphinx/source/Tutorials/PGN Requests.rst @@ -69,7 +69,7 @@ To do this, create a function that matches the type :code:`PGNRequestCallback`. .. code-block:: c++ bool example_proprietary_a_pgn_request_handler(std::uint32_t parameterGroupNumber, - isobus::ControlFunction *, + isobus::std::shared_ptr , bool &acknowledge, isobus::AcknowledgementType &acknowledgeType, void *) @@ -112,7 +112,7 @@ To do this, create a function that matches the type :code:`PGNRequestForRepetiti .. code-block:: c++ bool example_proprietary_a_request_for_repetition_rate_handler(std::uint32_t parameterGroupNumber, - isobus::ControlFunction *requestingControlFunction, + isobus::std::shared_ptr requestingControlFunction, std::uint32_t repetitionRate, void *) { 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 9c690041..7bc54b2b 100644 --- a/test/core_network_management_tests.cpp +++ b/test/core_network_management_tests.cpp @@ -18,10 +18,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) @@ -37,10 +40,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) @@ -95,7 +105,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; @@ -167,6 +177,8 @@ TEST(CORE_TESTS, CommandedAddress) std::this_thread::sleep_for(std::chrono::milliseconds(500)); EXPECT_EQ(0x04, testECU->get_address()); + + EXPECT_TRUE(testECU->destroy()); testPlugin.close(); CANHardwareInterface::stop(); } @@ -201,7 +213,7 @@ TEST(CORE_TESTS, InvalidatingControlFunctions) CANNetworkManager::CANNetwork.update(); std::vector testFilter = { NAMEFilter(NAME::NAMEParameters::IdentityNumber, 967) }; - PartneredControlFunction testPartner(0, testFilter); + auto testPartner = PartneredControlFunction::create(0, testFilter); std::uint64_t rawNAME = partnerName.get_full_name(); @@ -219,7 +231,7 @@ TEST(CORE_TESTS, InvalidatingControlFunctions) CANNetworkManager::process_receive_can_message_frame(testFrame); CANNetworkManager::CANNetwork.update(); - EXPECT_TRUE(testPartner.get_address_valid()); + EXPECT_TRUE(testPartner->get_address_valid()); // Request the address claim PGN testFrame.data[0] = (PGN & std::numeric_limits::max()); @@ -234,5 +246,6 @@ TEST(CORE_TESTS, InvalidatingControlFunctions) std::this_thread::sleep_for(std::chrono::seconds(2)); CANNetworkManager::CANNetwork.update(); - EXPECT_FALSE(testPartner.get_address_valid()); + EXPECT_FALSE(testPartner->get_address_valid()); + EXPECT_TRUE(testPartner->destroy()); } diff --git a/test/diagnostic_protocol_tests.cpp b/test/diagnostic_protocol_tests.cpp index ae63ebc9..f06a314d 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,7 @@ 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)); } + + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + 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/maintain_power_tests.cpp b/test/maintain_power_tests.cpp index 343ef36c..93e96858 100644 --- a/test/maintain_power_tests.cpp +++ b/test/maintain_power_tests.cpp @@ -65,7 +65,7 @@ TEST(MAINTAIN_POWER_TESTS, MessageParsing) TestDeviceNAME.set_device_class_instance(0); TestDeviceNAME.set_manufacturer_code(64); - auto testECU = std::make_shared(TestDeviceNAME, 0x82, 0); + auto testECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x82, 0); std::uint32_t waitingTimestamp_ms = SystemTiming::get_timestamp_ms(); while ((!testECU->get_address_valid()) && @@ -82,7 +82,8 @@ TEST(MAINTAIN_POWER_TESTS, MessageParsing) interfaceUnderTest.initialize(); EXPECT_TRUE(interfaceUnderTest.get_initialized()); - CANMessageFrame testFrame = { 0 }; + CANMessageFrame testFrame; + memset(&testFrame, 0, sizeof(testFrame)); testFrame.isExtendedFrame = true; // Get the virtual CAN plugin back to a known state @@ -103,7 +104,7 @@ TEST(MAINTAIN_POWER_TESTS, MessageParsing) testFrame.data[3] = 0x12; testFrame.data[4] = 0x00; testFrame.data[5] = 0x82; - testFrame.data[6] = 0x01; + testFrame.data[6] = 0x02; testFrame.data[7] = 0xA0; CANNetworkManager::process_receive_can_message_frame(testFrame); CANNetworkManager::CANNetwork.update(); @@ -239,6 +240,8 @@ TEST(MAINTAIN_POWER_TESTS, MessageParsing) EXPECT_FALSE(TestMaintainPowerInterface::wasKeySwitchTransitionCallbackHit); + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + EXPECT_TRUE(testECU->destroy(2)); CANHardwareInterface::stop(); } @@ -262,7 +265,7 @@ TEST(MAINTAIN_POWER_TESTS, MessageEncoding) TestDeviceNAME.set_device_class_instance(0); TestDeviceNAME.set_manufacturer_code(64); - auto testECU = std::make_shared(TestDeviceNAME, 0x48, 0); + auto testECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x48, 0); std::uint32_t waitingTimestamp_ms = SystemTiming::get_timestamp_ms(); while ((!testECU->get_address_valid()) && @@ -273,7 +276,8 @@ TEST(MAINTAIN_POWER_TESTS, MessageEncoding) ASSERT_TRUE(testECU->get_address_valid()); - CANMessageFrame testFrame = { 0 }; + CANMessageFrame testFrame; + memset(&testFrame, 0, sizeof(testFrame)); testFrame.isExtendedFrame = true; // Get the virtual CAN plugin back to a known state @@ -337,5 +341,8 @@ TEST(MAINTAIN_POWER_TESTS, MessageEncoding) EXPECT_EQ(0xFF, testFrame.data[7]); testPlugin.close(); + + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + EXPECT_TRUE(testECU->destroy(2)); CANHardwareInterface::stop(); } diff --git a/test/speed_distance_message_tests.cpp b/test/speed_distance_message_tests.cpp index 9e4380fb..90113283 100644 --- a/test/speed_distance_message_tests.cpp +++ b/test/speed_distance_message_tests.cpp @@ -103,7 +103,7 @@ TEST(SPEED_MESSAGE_TESTS, SpeedMessages) TestDeviceNAME.set_device_class_instance(0); TestDeviceNAME.set_manufacturer_code(64); - auto testECU = std::make_shared(TestDeviceNAME, 0x45, 0); + auto testECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x45, 0); CANMessageFrame testFrame; testFrame.timestamp_us = 0; @@ -364,6 +364,8 @@ TEST(SPEED_MESSAGE_TESTS, SpeedMessages) ASSERT_TRUE(testPlugin.read_frame(testFrame)); ASSERT_TRUE(testPlugin.read_frame(testFrame)); } + + EXPECT_TRUE(testECU->destroy()); CANHardwareInterface::stop(); } diff --git a/test/tc_client_tests.cpp b/test/tc_client_tests.cpp index be797c61..f3afddcd 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,10 +490,13 @@ 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), ""); + + //! @todo try to reduce the reference count, such that that we don't use a control function after it is destroyed + EXPECT_TRUE(internalECU->destroy(3)); } TEST(TASK_CONTROLLER_CLIENT_TESTS, BadICFDeathTest) @@ -497,10 +505,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 +544,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 +562,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 +590,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 +976,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 +985,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 +1127,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 +1165,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 +1173,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 +1351,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 +1363,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 +1422,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); + auto 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 +1450,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 +1701,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..0d2c5c65 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(); + + //! @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)); }