-
-
Notifications
You must be signed in to change notification settings - Fork 88
VT Client: Add a way to select VT object pool(s) to use based on VT server version #607
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ad3154
wants to merge
3
commits into
main
Choose a base branch
from
adrian/vt-client-earlier-version-check
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
examples/virtual_terminal/multiple_object_pools/CMakeLists.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| cmake_minimum_required(VERSION 3.16) | ||
| project(vt_client_multiple_object_pools_example) | ||
|
|
||
| if(NOT BUILD_EXAMPLES) | ||
| find_package(isobus REQUIRED) | ||
| endif() | ||
| find_package(Threads REQUIRED) | ||
|
|
||
| add_executable(VTClientMultiplePoolsExampleTarget main.cpp console_logger.cpp | ||
| objectPoolObjects.h) | ||
|
|
||
| target_compile_features(VTClientMultiplePoolsExampleTarget PUBLIC cxx_std_11) | ||
| set_target_properties(VTClientMultiplePoolsExampleTarget | ||
| PROPERTIES CXX_EXTENSIONS OFF) | ||
|
|
||
| target_link_libraries( | ||
| VTClientMultiplePoolsExampleTarget | ||
| PRIVATE isobus::Isobus isobus::HardwareIntegration Threads::Threads | ||
| isobus::Utility) | ||
|
|
||
| add_custom_command( | ||
| TARGET VTClientMultiplePoolsExampleTarget | ||
| POST_BUILD | ||
| COMMENT "Copying object pools to build directory" | ||
| COMMAND | ||
| ${CMAKE_COMMAND} -E copy | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/../version3_object_pool/VT3TestPool.iop | ||
| $<TARGET_FILE_DIR:VTClientMultiplePoolsExampleTarget>/VT3TestPool.iop | ||
| COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/window_masks.iop | ||
| $<TARGET_FILE_DIR:VTClientMultiplePoolsExampleTarget>/window_masks.iop | ||
| ) |
67 changes: 67 additions & 0 deletions
67
examples/virtual_terminal/multiple_object_pools/console_logger.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| #include "isobus/isobus/can_stack_logger.hpp" | ||
|
|
||
| #include <iostream> | ||
|
|
||
| // A log sink for the CAN stack | ||
| class CustomLogger : public isobus::CANStackLogger | ||
| { | ||
| public: | ||
| void sink_CAN_stack_log(CANStackLogger::LoggingLevel level, const std::string &text) override | ||
| { | ||
| switch (level) | ||
| { | ||
| case LoggingLevel::Debug: | ||
| { | ||
| std::cout << "[" | ||
| << "\033[1;36m" | ||
| << "Debug" | ||
| << "\033[0m" | ||
| << "]"; | ||
| } | ||
| break; | ||
|
|
||
| case LoggingLevel::Info: | ||
| { | ||
| std::cout << "[" | ||
| << "\033[1;32m" | ||
| << "Info" | ||
| << "\033[0m" | ||
| << "]"; | ||
| } | ||
| break; | ||
|
|
||
| case LoggingLevel::Warning: | ||
| { | ||
| std::cout << "[" | ||
| << "\033[1;33m" | ||
| << "Warn" | ||
| << "\033[0m" | ||
| << "]"; | ||
| } | ||
| break; | ||
|
|
||
| case LoggingLevel::Error: | ||
| { | ||
| std::cout << "[" | ||
| << "\033[1;31m" | ||
| << "Error" | ||
| << "\033[0m" | ||
| << "]"; | ||
| } | ||
| break; | ||
|
|
||
| case LoggingLevel::Critical: | ||
| { | ||
| std::cout << "[" | ||
| << "\033[1;35m" | ||
| << "Critical" | ||
| << "\033[0m" | ||
| << "]"; | ||
| } | ||
| break; | ||
| } | ||
| std::cout << text << std::endl; // Write the text to stdout | ||
| } | ||
| }; | ||
|
|
||
| static CustomLogger logger; |
220 changes: 220 additions & 0 deletions
220
examples/virtual_terminal/multiple_object_pools/main.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,220 @@ | ||
| #include "isobus/hardware_integration/available_can_drivers.hpp" | ||
| #include "isobus/hardware_integration/can_hardware_interface.hpp" | ||
| #include "isobus/isobus/can_network_manager.hpp" | ||
| #include "isobus/isobus/can_partnered_control_function.hpp" | ||
| #include "isobus/isobus/can_stack_logger.hpp" | ||
| #include "isobus/isobus/isobus_virtual_terminal_client.hpp" | ||
| #include "isobus/isobus/isobus_virtual_terminal_client_update_helper.hpp" | ||
| #include "isobus/utility/iop_file_interface.hpp" | ||
|
|
||
| #include "console_logger.cpp" | ||
| #include "objectPoolObjects.h" | ||
|
|
||
| #include <atomic> | ||
| #include <csignal> | ||
| #include <iostream> | ||
|
|
||
| //! It is discouraged to use global variables, but it is done here for simplicity. | ||
| static std::shared_ptr<isobus::VirtualTerminalClient> virtualTerminalClient = nullptr; | ||
| static std::shared_ptr<isobus::VirtualTerminalClientUpdateHelper> virtualTerminalUpdateHelper = nullptr; | ||
| static std::atomic_bool running = { true }; | ||
|
|
||
| void signal_handler(int) | ||
| { | ||
| running = false; | ||
| } | ||
|
|
||
| // This callback will provide us with event driven notifications of softkey presses from the stack | ||
| void handle_softkey_event(const isobus::VirtualTerminalClient::VTKeyEvent &event) | ||
| { | ||
| if (event.keyNumber == 0) | ||
| { | ||
| // We have the alarm ACK code, so if we have an active alarm, acknowledge it by going back to the main runscreen | ||
| virtualTerminalUpdateHelper->set_active_data_or_alarm_mask(example_WorkingSet, mainRunscreen_DataMask); | ||
| } | ||
|
|
||
| switch (event.keyEvent) | ||
| { | ||
| case isobus::VirtualTerminalClient::KeyActivationCode::ButtonUnlatchedOrReleased: | ||
| { | ||
| switch (event.objectID) | ||
| { | ||
| case alarm_SoftKey: | ||
| { | ||
| virtualTerminalUpdateHelper->set_active_data_or_alarm_mask(example_WorkingSet, example_AlarmMask); | ||
| } | ||
| break; | ||
|
|
||
| case acknowledgeAlarm_SoftKey: | ||
| { | ||
| virtualTerminalUpdateHelper->set_active_data_or_alarm_mask(example_WorkingSet, mainRunscreen_DataMask); | ||
| } | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
| } | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| // This callback will provide us with event driven notifications of button presses from the stack | ||
| void handle_button_event(const isobus::VirtualTerminalClient::VTKeyEvent &event) | ||
| { | ||
| switch (event.keyEvent) | ||
| { | ||
| case isobus::VirtualTerminalClient::KeyActivationCode::ButtonUnlatchedOrReleased: | ||
| case isobus::VirtualTerminalClient::KeyActivationCode::ButtonStillHeld: | ||
| { | ||
| switch (event.objectID) | ||
| { | ||
| case Plus_Button: | ||
| { | ||
| virtualTerminalUpdateHelper->increase_numeric_value(ButtonExampleNumber_VarNum); | ||
| } | ||
| break; | ||
|
|
||
| case Minus_Button: | ||
| { | ||
| virtualTerminalUpdateHelper->decrease_numeric_value(ButtonExampleNumber_VarNum); | ||
| } | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
| } | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| int main() | ||
| { | ||
| std::signal(SIGINT, signal_handler); | ||
|
|
||
| // Automatically load the desired CAN driver based on the available drivers | ||
| std::shared_ptr<isobus::CANHardwarePlugin> canDriver = nullptr; | ||
| #if defined(ISOBUS_SOCKETCAN_AVAILABLE) | ||
| canDriver = std::make_shared<isobus::SocketCANInterface>("can0"); | ||
| #elif defined(ISOBUS_WINDOWSPCANBASIC_AVAILABLE) | ||
| canDriver = std::make_shared<isobus::PCANBasicWindowsPlugin>(PCAN_USBBUS1); | ||
| #elif defined(ISOBUS_WINDOWSINNOMAKERUSB2CAN_AVAILABLE) | ||
| canDriver = std::make_shared<isobus::InnoMakerUSB2CANWindowsPlugin>(0); // CAN0 | ||
| #elif defined(ISOBUS_MACCANPCAN_AVAILABLE) | ||
| canDriver = std::make_shared<isobus::MacCANPCANPlugin>(PCAN_USBBUS1); | ||
| #elif defined(ISOBUS_SYS_TEC_AVAILABLE) | ||
| canDriver = std::make_shared<isobus::SysTecWindowsPlugin>(); | ||
| #endif | ||
| if (nullptr == canDriver) | ||
| { | ||
| std::cout << "Unable to find a CAN driver. Please make sure you have one of the above drivers installed with the library." << std::endl; | ||
| std::cout << "If you want to use a different driver, please add it to the list above." << std::endl; | ||
| return -1; | ||
| } | ||
|
|
||
| isobus::CANStackLogger::set_can_stack_logger_sink(&logger); | ||
| isobus::CANStackLogger::set_log_level(isobus::CANStackLogger::LoggingLevel::Info); // Change this to Debug to see more information | ||
| isobus::CANHardwareInterface::set_number_of_can_channels(1); | ||
| isobus::CANHardwareInterface::assign_can_channel_frame_handler(0, canDriver); | ||
|
|
||
| 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; | ||
| } | ||
|
|
||
| std::this_thread::sleep_for(std::chrono::milliseconds(250)); | ||
|
|
||
| isobus::NAME TestDeviceNAME(0); | ||
|
|
||
| //! Make sure you change these for your device!!!! | ||
| TestDeviceNAME.set_arbitrary_address_capable(true); | ||
| TestDeviceNAME.set_industry_group(1); | ||
| TestDeviceNAME.set_device_class(0); | ||
| TestDeviceNAME.set_function_code(static_cast<std::uint8_t>(isobus::NAME::Function::SteeringControl)); | ||
| TestDeviceNAME.set_identity_number(2); | ||
| TestDeviceNAME.set_ecu_instance(0); | ||
| TestDeviceNAME.set_function_instance(0); | ||
| TestDeviceNAME.set_device_class_instance(0); | ||
| TestDeviceNAME.set_manufacturer_code(1407); | ||
|
|
||
| std::vector<std::uint8_t> version3pool = isobus::IOPFileInterface::read_iop_file("VT3TestPool.iop"); | ||
| std::vector<std::uint8_t> version4pool = isobus::IOPFileInterface::read_iop_file("window_masks.iop"); | ||
|
|
||
| if (version3pool.empty()) | ||
| { | ||
| std::cout << "Failed to load object pool from VT3TestPool.iop" << std::endl; | ||
| return -3; | ||
| } | ||
| std::cout << "Loaded object pool from VT3TestPool.iop" << std::endl; | ||
|
|
||
| if (version4pool.empty()) | ||
| { | ||
| std::cout << "Failed to load object pool from window_masks.iop" << std::endl; | ||
| return -4; | ||
| } | ||
| std::cout << "Loaded object pool from window_masks.iop" << std::endl; | ||
|
|
||
| // Generate a unique version string for this object pool (this is optional, and is entirely application specific behavior) | ||
| std::string objectPoolHash = ""; | ||
|
|
||
| const isobus::NAMEFilter filterVirtualTerminal(isobus::NAME::NAMEParameters::FunctionCode, static_cast<std::uint8_t>(isobus::NAME::Function::VirtualTerminal)); | ||
| const std::vector<isobus::NAMEFilter> vtNameFilters = { filterVirtualTerminal }; | ||
| auto TestInternalECU = isobus::CANNetworkManager::CANNetwork.create_internal_control_function(TestDeviceNAME, 0); | ||
| auto TestPartnerVT = isobus::CANNetworkManager::CANNetwork.create_partnered_control_function(0, vtNameFilters); | ||
|
|
||
| virtualTerminalClient = std::make_shared<isobus::VirtualTerminalClient>(TestPartnerVT, TestInternalECU); | ||
| virtualTerminalClient->get_vt_soft_key_event_dispatcher().add_listener(handle_softkey_event); | ||
| virtualTerminalClient->get_vt_button_event_dispatcher().add_listener(handle_button_event); | ||
| virtualTerminalClient->set_on_ready_for_object_pool_callback([&version3pool, &version4pool, objectPoolHash](isobus::VirtualTerminalClient::VTVersion version) { | ||
| // You can check the connected VT version if you need to know what features are available, and select which object pool(s) to use based on that. | ||
| // This is optional though. If you want, you can just call set_object_pool() blindly exactly one time at any point if you want to try to use the same object pool for all VT versions. | ||
| switch (virtualTerminalClient->get_connected_vt_version()) | ||
| { | ||
| case isobus::VirtualTerminalClient::VTVersion::Version3: | ||
| { | ||
| // For version 3, we upload a base pool with only VT version 3 complaint objects | ||
| virtualTerminalClient->set_object_pool(0, version3pool.data(), version3pool.size(), objectPoolHash); | ||
| } | ||
| break; | ||
|
|
||
| case isobus::VirtualTerminalClient::VTVersion::Version4: | ||
| case isobus::VirtualTerminalClient::VTVersion::Version5: | ||
| case isobus::VirtualTerminalClient::VTVersion::Version6: | ||
| { | ||
| // For version 4, 5, and 6, we upload the same base pool as version 3, but also upload a second pool with version 4 objects | ||
| virtualTerminalClient->set_object_pool(0, version3pool.data(), version3pool.size(), objectPoolHash); | ||
| virtualTerminalClient->set_object_pool(1, version4pool.data(), version4pool.size(), objectPoolHash); | ||
| } | ||
| break; | ||
|
|
||
| default: | ||
| { | ||
| // Either we're not ready yet, or we don't have an object pool for this version | ||
| } | ||
| break; | ||
| } | ||
| }); | ||
| virtualTerminalClient->initialize(true); | ||
|
|
||
| virtualTerminalUpdateHelper = std::make_shared<isobus::VirtualTerminalClientUpdateHelper>(virtualTerminalClient); | ||
| virtualTerminalUpdateHelper->add_tracked_numeric_value(ButtonExampleNumber_VarNum, 214748364); // In the object pool the output number has an offset of -214748364 so we use this to represent 0. | ||
| virtualTerminalUpdateHelper->initialize(); | ||
|
|
||
| while (running) | ||
| { | ||
| // CAN stack runs in other threads. Do nothing forever. | ||
| std::this_thread::sleep_for(std::chrono::milliseconds(1000)); | ||
| } | ||
|
|
||
| virtualTerminalClient->terminate(); | ||
| isobus::CANHardwareInterface::stop(); | ||
| return 0; | ||
| } | ||
36 changes: 36 additions & 0 deletions
36
examples/virtual_terminal/multiple_object_pools/objectPoolObjects.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| // This is a file that will be auto-generated by your object pool designer application. | ||
| // These are the object IDs for the objects in the object pool | ||
| #define UNDEFINED 65535 //0xFFFF | ||
| #define example_WorkingSet 0 //0x0000 | ||
| #define mainRunscreen_DataMask 1000 //0x03E8 | ||
| #define example_AlarmMask 2000 //0x07D0 | ||
| #define exampleNumberInc_Container 3000 //0x0BB8 | ||
| #define mainRunscreen_SoftKeyMask 4000 //0x0FA0 | ||
| #define alarm_SKeyMask 4001 //0x0FA1 | ||
| #define alarm_SoftKey 5000 //0x1388 | ||
| #define acknowledgeAlarm_SoftKey 5001 //0x1389 | ||
| #define Plus_Button 6000 //0x1770 | ||
| #define Minus_Button 6001 //0x1771 | ||
| #define Title_OutStr 11000 //0x2AF8 | ||
| #define MainDescription_OutStr 11001 //0x2AF9 | ||
| #define temp_OutStr_ID_11002 11002 //0x2AFA | ||
| #define temp_OutStr_ID_11003 11003 //0x2AFB | ||
| #define AlarmMaskTitle_OutStr 11004 //0x2AFC | ||
| #define exampleOutput_OutNum 12000 //0x2EE0 | ||
| #define Title_OutRect 14000 //0x36B0 | ||
| #define MainRunscreenBackground_OutRect 14001 //0x36B1 | ||
| #define avatar_OutPict 20000 //0x4E20 | ||
| #define warningIcon_OutPict 20001 //0x4E21 | ||
| #define redAlert_OutPict 20002 //0x4E22 | ||
| #define greenCheck_OutPict 20003 //0x4E23 | ||
| #define ButtonExampleNumber_VarNum 21000 //0x5208 | ||
| #define title_OutStr 22000 //0x55F0 | ||
| #define MainDescription_VarStr 22001 //0x55F1 | ||
| #define alarmMaskTitle_OutStr 22002 //0x55F2 | ||
| #define ExampleAlarmMask_VarStr 22003 //0x55F3 | ||
| #define temp_FontAttr_ID_23000 23000 //0x59D8 | ||
| #define temp_FontAttr_ID_23001 23001 //0x59D9 | ||
| #define black48x64_FontAttr 23002 //0x59DA | ||
| #define solidBlack_LineAttr 24000 //0x5DC0 | ||
| #define solidWhite_FillAttr 25000 //0x61A8 | ||
| #define exampleNumberInc_ObjPtr 27000 //0x6978 |
Binary file not shown.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a (void)version to suppress the unused parameter warning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead, I'd say we remove the "version" parameter of the callback altogether. There are many more requirements possible as can be seen in #376. We can just let the application access those via more member functions like
get_connected_vt_version()does for the version