diff --git a/examples/file_server_client/main.cpp b/examples/file_server_client/main.cpp index 0c42b0a73..2005f981d 100644 --- a/examples/file_server_client/main.cpp +++ b/examples/file_server_client/main.cpp @@ -26,11 +26,6 @@ void update_CAN_network(void *) isobus::CANNetworkManager::CANNetwork.update(); } -void raw_can_glue(isobus::HardwareInterfaceCANFrame &rawFrame, void *parentPointer) -{ - isobus::CANNetworkManager::CANNetwork.can_lib_process_rx_message(rawFrame, parentPointer); -} - enum class ExampleStateMachineState { OpenFile, @@ -45,19 +40,16 @@ int main() { std::signal(SIGINT, signal_handler); isobus::CANStackLogger::set_can_stack_logger_sink(&logger); - isobus::CANStackLogger::set_log_level(isobus::CANStackLogger::LoggingLevel::Debug); // Change this to Debug to see more information - std::shared_ptr TestInternalECU = nullptr; - std::shared_ptr TestPartnerFS = nullptr; - std::shared_ptr TestFileServerClient = nullptr; - std::shared_ptr canDriver = nullptr; + isobus::CANStackLogger::set_log_level(isobus::CANStackLogger::LoggingLevel::Debug); + std::shared_ptr canDriver = nullptr; #if defined(ISOBUS_SOCKETCAN_AVAILABLE) - canDriver = std::make_shared("can0"); + canDriver = std::make_shared("can0"); #elif defined(ISOBUS_WINDOWSPCANBASIC_AVAILABLE) - canDriver = std::make_shared(PCAN_USBBUS1); + canDriver = std::make_shared(PCAN_USBBUS1); #elif defined(ISOBUS_WINDOWSINNOMAKERUSB2CAN_AVAILABLE) - canDriver = std::make_shared(0); // CAN0 + canDriver = std::make_shared(0); // CAN0 #elif defined(ISOBUS_MACCANPCAN_AVAILABLE) - canDriver = std::make_shared(PCAN_USBBUS1); + canDriver = std::make_shared(PCAN_USBBUS1); #endif if (nullptr == canDriver) @@ -67,24 +59,20 @@ int main() return -1; } - CANHardwareInterface::set_number_of_can_channels(1); - CANHardwareInterface::assign_can_channel_frame_handler(0, canDriver); + isobus::CANHardwareInterface::set_number_of_can_channels(1); + isobus::CANHardwareInterface::assign_can_channel_frame_handler(0, canDriver); - if ((!CANHardwareInterface::start()) || (!canDriver->get_is_valid())) + if ((!isobus::CANHardwareInterface::start()) || (!canDriver->get_is_valid())) { std::cout << "Failed to start hardware interface. The CAN driver might be invalid." << std::endl; return -2; } - CANHardwareInterface::add_can_lib_update_callback(update_CAN_network, nullptr); - CANHardwareInterface::add_raw_can_message_rx_callback(raw_can_glue, nullptr); - std::this_thread::sleep_for(std::chrono::milliseconds(250)); isobus::NAME TestDeviceNAME(0); - // Make sure you change these for your device!!!! - // This is an example device that is using a manufacturer code that is currently unused at time of writing + // Consider customizing these values to match your device TestDeviceNAME.set_arbitrary_address_capable(true); TestDeviceNAME.set_industry_group(1); TestDeviceNAME.set_device_class(0); @@ -93,22 +81,22 @@ int main() TestDeviceNAME.set_ecu_instance(0); TestDeviceNAME.set_function_instance(0); TestDeviceNAME.set_device_class_instance(0); - TestDeviceNAME.set_manufacturer_code(64); + TestDeviceNAME.set_manufacturer_code(1407); std::vector fsNameFilters; const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::FileServerOrPrinter)); fsNameFilters.push_back(testFilter); - TestInternalECU = std::make_shared(TestDeviceNAME, 0x1C, 0); - TestPartnerFS = std::make_shared(0, fsNameFilters); - TestFileServerClient = std::make_shared(TestPartnerFS, TestInternalECU); + auto TestInternalECU = isobus::CANNetworkManager::CANNetwork.create_internal_control_function(TestDeviceNAME, 0); + auto TestPartnerFS = isobus::CANNetworkManager::CANNetwork.create_partnered_control_function(0, fsNameFilters); + auto TestFileServerClient = std::make_shared(TestPartnerFS, TestInternalECU); TestFileServerClient->initialize(true); ExampleStateMachineState state = ExampleStateMachineState::OpenFile; std::string fileNameToUse = "FSExampleFile.txt"; std::uint8_t fileHandle = isobus::FileServerClient::INVALID_FILE_HANDLE; - const std::string fileExampleContents = "This is an example file! Visit us on Github https://github.com/ad3154/Isobus-plus-plus"; + const std::string fileExampleContents = "This is an example file! Visit us on Github https://github.com/Open-Agriculture/AgIsoStack-plus-plus"; while (running) { @@ -179,6 +167,6 @@ int main() std::this_thread::sleep_for(std::chrono::milliseconds(100)); } - CANHardwareInterface::stop(); + isobus::CANHardwareInterface::stop(); return 0; } diff --git a/isobus/include/isobus/isobus/isobus_file_server_client.hpp b/isobus/include/isobus/isobus/isobus_file_server_client.hpp index f8aa0bd5f..700680dc8 100644 --- a/isobus/include/isobus/isobus/isobus_file_server_client.hpp +++ b/isobus/include/isobus/isobus/isobus_file_server_client.hpp @@ -11,7 +11,6 @@ #include "isobus/isobus/can_network_manager.hpp" #include "isobus/isobus/can_partnered_control_function.hpp" -#include "isobus/isobus/can_protocol.hpp" #include "isobus/utility/processing_flags.hpp" #include @@ -289,7 +288,7 @@ namespace isobus InitializeVolumeRequest = 0x40 ///< Prepare the volume to accept files and directories. All data is lost upon completion }; - /// @brief Enuerates the transmit flags (CAN messages that support non-state-machine-driven retries) + /// @brief Enumerates the transmit flags (CAN messages that support non-state-machine-driven retries) enum class TransmitFlags { ClientToServerStatus = 0, ///< Flag to send the maintenance message to the file server @@ -308,7 +307,7 @@ namespace isobus FileState state = FileState::Uninitialized; ///< A sub-state-machine state for the file FileOpenMode openMode = FileOpenMode::OpenFileForReadingOnly; ///< The file open mode (read only, write only, etc) FilePointerMode pointerMode = FilePointerMode::AppendMode; ///< Where the file pointer should be set for this file - std::uint32_t timstamp_ms = 0; ///< A timestamp to track when file operations take too long + std::uint32_t timestamp_ms = 0; ///< A timestamp to track when file operations take too long std::uint8_t attributesBitField = 0; ///< The reported file attributes std::uint8_t transactionNumberForRequest = 0; ///< The TAN for the latest request corresponding to this file std::uint8_t handle = INVALID_FILE_HANDLE; ///< The file handle associated with this file @@ -331,12 +330,12 @@ namespace isobus /// @brief A generic way for a protocol to process a received message /// @param[in] message A received CAN message - void process_message(CANMessage *const message); + void process_message(const CANMessage &message); /// @brief A generic way for a protocol to process a received message /// @param[in] message A received CAN message /// @param[in] parent Provides the context to the actual TP manager object - static void process_message(CANMessage *const message, void *parent); + static void process_message(const CANMessage &message, void *parent); /// @brief The data callback passed to the network manger's send function for the transport layer messages /// @details We upload the data with callbacks to avoid making a complete copy of the data to diff --git a/isobus/src/isobus_file_server_client.cpp b/isobus/src/isobus_file_server_client.cpp index 9cdac4b97..bd0604d68 100644 --- a/isobus/src/isobus_file_server_client.cpp +++ b/isobus/src/isobus_file_server_client.cpp @@ -239,9 +239,9 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ClientToFileServer), buffer.data(), buffer.size(), - myControlFunction.get(), - partnerControlFunction.get(), - CANIdentifier::PriorityLowest7); + myControlFunction, + partnerControlFunction, + CANIdentifier::CANPriority::PriorityLowest7); } bool FileServerClient::initialize(bool spawnThread) @@ -464,21 +464,20 @@ namespace isobus } } - void FileServerClient::process_message(CANMessage *const message) + void FileServerClient::process_message(const CANMessage &message) { - if ((nullptr != message) && - (nullptr != partnerControlFunction) && - (static_cast(CANLibParameterGroupNumber::FileServerToClient) == message->get_identifier().get_parameter_group_number()) && - ((message->get_source_control_function()->get_address() == partnerControlFunction->get_address()) || - (nullptr == message->get_destination_control_function()))) + if ((nullptr != partnerControlFunction) && + (static_cast(CANLibParameterGroupNumber::FileServerToClient) == message.get_identifier().get_parameter_group_number()) && + ((message.get_source_control_function()->get_address() == partnerControlFunction->get_address()) || + (nullptr == message.get_destination_control_function()))) { - auto &messageData = message->get_data(); + auto &messageData = message.get_data(); switch (messageData[0]) { case static_cast(FileServerToClientMultiplexor::FileServerStatus): { - if (CAN_DATA_LENGTH == message->get_data_length()) + if (CAN_DATA_LENGTH == message.get_data_length()) { if (0 == lastServerStatusTimestamp_ms) { @@ -504,7 +503,7 @@ namespace isobus case static_cast(FileServerToClientMultiplexor::GetFileServerPropertiesResponse): { - if (CAN_DATA_LENGTH == message->get_data_length()) + if (CAN_DATA_LENGTH == message.get_data_length()) { if (StateMachineState::WaitForGetFileServerPropertiesResponse == get_state()) { @@ -532,7 +531,7 @@ namespace isobus case static_cast(FileServerToClientMultiplexor::ChangeCurrentDirectoryResponse): { - if (CAN_DATA_LENGTH == message->get_data_length()) + if (CAN_DATA_LENGTH == message.get_data_length()) { if (StateMachineState::WaitForChangeToManufacturerDirectoryResponse == get_state()) { @@ -574,7 +573,7 @@ namespace isobus case static_cast(FileServerToClientMultiplexor::OpenFileResponse): { - if (CAN_DATA_LENGTH == message->get_data_length()) + if (CAN_DATA_LENGTH == message.get_data_length()) { bool foundMatchingFileInList = false; @@ -615,7 +614,7 @@ namespace isobus case static_cast(FileServerToClientMultiplexor::CloseFileResponse): { - if (CAN_DATA_LENGTH == message->get_data_length()) + if (CAN_DATA_LENGTH == message.get_data_length()) { bool foundMatchingFileInList = false; @@ -655,7 +654,7 @@ namespace isobus case static_cast(FileServerToClientMultiplexor::WriteFileResponse): { - if (CAN_DATA_LENGTH == message->get_data_length()) + if (CAN_DATA_LENGTH == message.get_data_length()) { bool foundMatchingFileInList = false; @@ -726,11 +725,11 @@ namespace isobus } } - void FileServerClient::process_message(CANMessage *const message, void *parent) + void FileServerClient::process_message(const CANMessage &message, void *parent) { if (nullptr != parent) { - reinterpret_cast(parent)->process_message(message); + static_cast(parent)->process_message(message); } } @@ -805,9 +804,9 @@ namespace isobus retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ClientToFileServer), buffer.data(), buffer.size(), - myControlFunction.get(), - partnerControlFunction.get(), - CANIdentifier::PriorityLowest7); + myControlFunction, + partnerControlFunction, + CANIdentifier::CANPriority::PriorityLowest7); } return retVal; } @@ -826,9 +825,9 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ClientToFileServer), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), - CANIdentifier::PriorityLowest7); + myControlFunction, + partnerControlFunction, + CANIdentifier::CANPriority::PriorityLowest7); } bool FileServerClient::send_close_file(std::shared_ptr fileMetadata) const @@ -844,9 +843,9 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ClientToFileServer), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), - CANIdentifier::PriorityLowest7); + myControlFunction, + partnerControlFunction, + CANIdentifier::CANPriority::PriorityLowest7); } bool FileServerClient::send_get_file_server_properties() const @@ -863,9 +862,9 @@ namespace isobus return CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ClientToFileServer), buffer.data(), CAN_DATA_LENGTH, - myControlFunction.get(), - partnerControlFunction.get(), - CANIdentifier::PriorityLowest7); + myControlFunction, + partnerControlFunction, + CANIdentifier::CANPriority::PriorityLowest7); } bool FileServerClient::send_open_file(std::shared_ptr fileMetadata) const @@ -896,19 +895,16 @@ namespace isobus buffer[5 + i] = fileMetadata->fileName[i]; } - if (buffer.size() < CAN_DATA_LENGTH) + while (buffer.size() < CAN_DATA_LENGTH) { - for (std::size_t i = buffer.size(); i < CAN_DATA_LENGTH; i++) - { - buffer[i] = 0xFF; - } + buffer.push_back(0xFF); } retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ClientToFileServer), buffer.data(), buffer.size(), - myControlFunction.get(), - partnerControlFunction.get(), - CANIdentifier::PriorityLowest7); + myControlFunction, + partnerControlFunction, + CANIdentifier::CANPriority::PriorityLowest7); } return retVal; } @@ -930,7 +926,7 @@ namespace isobus if (nullptr != fileMetadata) { fileMetadata->state = state; - fileMetadata->timstamp_ms = SystemTiming::get_timestamp_ms(); + fileMetadata->timestamp_ms = SystemTiming::get_timestamp_ms(); } } @@ -956,7 +952,7 @@ namespace isobus { set_file_state(file, FileState::WaitForOpenFileResponse); } - else if (SystemTiming::time_expired_ms(file->timstamp_ms, GENERAL_OPERATION_TIMEOUT)) + else if (SystemTiming::time_expired_ms(file->timestamp_ms, GENERAL_OPERATION_TIMEOUT)) { CANStackLogger::error("[FS]: Timeout trying to send an open file message."); set_file_state(file, FileState::FileOpenFailed); @@ -966,7 +962,7 @@ namespace isobus case FileState::WaitForOpenFileResponse: { - if (SystemTiming::time_expired_ms(file->timstamp_ms, GENERAL_OPERATION_TIMEOUT)) + if (SystemTiming::time_expired_ms(file->timestamp_ms, GENERAL_OPERATION_TIMEOUT)) { CANStackLogger::error("[FS]: Timeout waiting to an open file response message."); set_file_state(file, FileState::FileOpenFailed); @@ -980,7 +976,7 @@ namespace isobus { set_file_state(file, FileState::WaitForCloseFileResponse); } - else if (SystemTiming::time_expired_ms(file->timstamp_ms, GENERAL_OPERATION_TIMEOUT)) + else if (SystemTiming::time_expired_ms(file->timestamp_ms, GENERAL_OPERATION_TIMEOUT)) { CANStackLogger::error("[FS]: Timeout trying to send a close file message."); } @@ -989,7 +985,7 @@ namespace isobus case FileState::WaitForCloseFileResponse: { - if (SystemTiming::time_expired_ms(file->timstamp_ms, GENERAL_OPERATION_TIMEOUT)) + if (SystemTiming::time_expired_ms(file->timestamp_ms, GENERAL_OPERATION_TIMEOUT)) { // todo } diff --git a/test/file_server_client_tests.cpp b/test/file_server_client_tests.cpp index 9e41b3678..eb75d2f97 100644 --- a/test/file_server_client_tests.cpp +++ b/test/file_server_client_tests.cpp @@ -5,6 +5,8 @@ #include "isobus/isobus/isobus_file_server_client.hpp" #include "isobus/utility/system_timing.hpp" +#include "helpers/control_function_helpers.hpp" + using namespace isobus; class DerivedTestFileServerClient : public FileServerClient @@ -61,30 +63,15 @@ TEST(FILE_SERVER_CLIENT_TESTS, StateMachineTests) CANHardwareInterface::set_number_of_can_channels(1); CANHardwareInterface::assign_can_channel_frame_handler(0, std::make_shared()); - CANHardwareInterface::add_can_lib_update_callback( - [](void *) { - CANNetworkManager::CANNetwork.update(); - }, - nullptr); CANHardwareInterface::start(); NAME clientNAME(0); clientNAME.set_industry_group(2); clientNAME.set_ecu_instance(4); clientNAME.set_function_code(static_cast(NAME::Function::DriveAxleControlBrakes)); - auto internalECU = std::make_shared(clientNAME, 0x93, 0); - - HardwareInterfaceCANFrame 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)); - } + auto internalECU = test_helpers::claim_internal_control_function(0x93, 0); - ASSERT_TRUE(internalECU->get_address_valid()); + CANMessageFrame testFrame = {}; std::vector fsNameFilters; const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::FileServer)); @@ -105,12 +92,17 @@ TEST(FILE_SERVER_CLIENT_TESTS, StateMachineTests) testFrame.data[5] = 0x52; testFrame.data[6] = 0x00; testFrame.data[7] = 0xA0; - CANNetworkManager::CANNetwork.can_lib_process_rx_message(testFrame, nullptr); + CANNetworkManager::CANNetwork.process_receive_can_message_frame(testFrame); + CANNetworkManager::CANNetwork.update(); DerivedTestFileServerClient interfaceUnderTest(tcPartner, internalECU); // Test initial state EXPECT_EQ(FileServerClient::StateMachineState::Disconnected, interfaceUnderTest.get_state()); + + CANHardwareInterface::stop(); + CANNetworkManager::CANNetwork.update(); //! @todo: quick hack for clearing the transmit queue, can be removed once network manager' singleton is removed + CANNetworkManager::CANNetwork.deactivate_control_function(internalECU); } TEST(FILE_SERVER_CLIENT_TESTS, MessageEncoding) @@ -120,35 +112,17 @@ TEST(FILE_SERVER_CLIENT_TESTS, MessageEncoding) CANHardwareInterface::set_number_of_can_channels(1); CANHardwareInterface::assign_can_channel_frame_handler(0, std::make_shared()); - CANHardwareInterface::add_can_lib_update_callback( - [](void *) { - CANNetworkManager::CANNetwork.update(); - }, - nullptr); CANHardwareInterface::start(); - NAME clientNAME(0); - clientNAME.set_industry_group(2); - clientNAME.set_function_code(static_cast(NAME::Function::AlarmDevice)); - auto internalECU = std::make_shared(clientNAME, 0x90, 0); - - HardwareInterfaceCANFrame testFrame; + auto internalECU = test_helpers::claim_internal_control_function(0x90, 0); - 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)); - } - - ASSERT_TRUE(internalECU->get_address_valid()); + CANMessageFrame testFrame = {}; std::vector fsNameFilters; const isobus::NAMEFilter testFilter(isobus::NAME::NAMEParameters::FunctionCode, static_cast(isobus::NAME::Function::FileServer)); fsNameFilters.push_back(testFilter); - auto fileServerPartner = std::make_shared(0, fsNameFilters); + auto fileServerPartner = CANNetworkManager::CANNetwork.create_partnered_control_function(0, fsNameFilters); // Force claim a partner testFrame.dataLength = 8; @@ -163,7 +137,8 @@ TEST(FILE_SERVER_CLIENT_TESTS, MessageEncoding) testFrame.data[5] = 0x52; testFrame.data[6] = 0x00; testFrame.data[7] = 0xA0; - CANNetworkManager::CANNetwork.can_lib_process_rx_message(testFrame, nullptr); + CANNetworkManager::CANNetwork.process_receive_can_message_frame(testFrame); + CANNetworkManager::CANNetwork.update(); DerivedTestFileServerClient interfaceUnderTest(fileServerPartner, internalECU); @@ -218,4 +193,8 @@ TEST(FILE_SERVER_CLIENT_TESTS, MessageEncoding) EXPECT_EQ('/', testFrame.data[5]); // Path EXPECT_EQ(0xFF, testFrame.data[6]); // Reserved (due to length of 2) EXPECT_EQ(0xFF, testFrame.data[7]); // Reserved (due to length of 2) + + CANHardwareInterface::stop(); + CANNetworkManager::CANNetwork.update(); //! @todo: quick hack for clearing the transmit queue, can be removed once network manager' singleton is removed + CANNetworkManager::CANNetwork.deactivate_control_function(internalECU); }