From 307630d15c3df08751799c9c80fb2a5e6e8c9ce8 Mon Sep 17 00:00:00 2001 From: Daan Steenbergen Date: Sun, 17 Dec 2023 18:06:07 +0100 Subject: [PATCH] feat(vt): add activation message responses --- .../isobus/isobus_virtual_terminal_client.hpp | 4 +- isobus/src/isobus_virtual_terminal_client.cpp | 283 ++++++++++++++++-- 2 files changed, 262 insertions(+), 25 deletions(-) diff --git a/isobus/include/isobus/isobus/isobus_virtual_terminal_client.hpp b/isobus/include/isobus/isobus/isobus_virtual_terminal_client.hpp index 0b027284..c88a65b1 100644 --- a/isobus/include/isobus/isobus/isobus_virtual_terminal_client.hpp +++ b/isobus/include/isobus/isobus/isobus_virtual_terminal_client.hpp @@ -1123,10 +1123,10 @@ namespace isobus /// @returns The VT version supported supported by the VT server VTVersion get_connected_vt_version() const; - /// @brief Returns if the VT version is supported by the VT server + /// @brief Returns whether the VT version is supported by the VT server /// @param[in] value The VT version to check against /// @returns true if the VT version is supported by the VT server - bool get_vt_version_supported(VTVersion value) const; + bool is_vt_version_supported(VTVersion value) const; /// @brief Returns the current data mask displayed by the VT server /// @returns The object ID of the data mask visible diff --git a/isobus/src/isobus_virtual_terminal_client.cpp b/isobus/src/isobus_virtual_terminal_client.cpp index 5f1fa5c3..f328e73a 100644 --- a/isobus/src/isobus_virtual_terminal_client.cpp +++ b/isobus/src/isobus_virtual_terminal_client.cpp @@ -1197,7 +1197,7 @@ namespace isobus return retVal; } - bool VirtualTerminalClient::get_vt_version_supported(VTVersion minimumVersion) const + bool VirtualTerminalClient::is_vt_version_supported(VTVersion minimumVersion) const { bool retVal = false; @@ -2092,7 +2092,7 @@ namespace isobus { errorCode |= 0x01; } - if ((isAlreadyAssigned) && (false == get_vt_version_supported(VTVersion::Version6))) + if ((isAlreadyAssigned) && (false == is_vt_version_supported(VTVersion::Version6))) { errorCode |= 0x02; } @@ -2325,12 +2325,35 @@ namespace isobus std::uint16_t objectID = message.get_uint16_at(2); std::uint16_t parentObjectID = message.get_uint16_at(4); std::uint8_t keyNumber = message.get_uint8_at(6); - if (parentVT->get_vt_version_supported(VTVersion::Version6)) + std::uint8_t transactionNumber = 0xF; + if (parentVT->is_vt_version_supported(VTVersion::Version6)) { - //! @todo process TAN + transactionNumber = message.get_uint8_at(7) >> 4; } parentVT->softKeyEventDispatcher.invoke({ parentVT, objectID, parentObjectID, keyNumber, static_cast(keyCode) }); + + // Send response + std::array buffer{ + static_cast(Function::SoftKeyActivationMessage), + keyCode, + static_cast(objectID), + static_cast(objectID >> 8), + static_cast(parentObjectID), + static_cast(parentObjectID >> 8), + keyNumber, + 0xFF, + }; + if (parentVT->is_vt_version_supported(VTVersion::Version6)) + { + buffer[7] = static_cast(transactionNumber << 4 | 0x0F); + } + CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), + buffer.data(), + CAN_DATA_LENGTH, + parentVT->myControlFunction, + parentVT->partnerControlFunction, + CANIdentifier::CANPriority::Priority5); } } break; @@ -2343,11 +2366,35 @@ namespace isobus std::uint16_t objectID = message.get_uint16_at(2); std::uint16_t parentObjectID = message.get_uint16_at(4); std::uint8_t keyNumber = message.get_uint8_at(6); - if (parentVT->get_vt_version_supported(VTVersion::Version6)) + std::uint8_t transactionNumber = 0xF; + if (parentVT->is_vt_version_supported(VTVersion::Version6)) { - //! @todo process TAN + transactionNumber = message.get_uint8_at(7) >> 4; } + parentVT->buttonEventDispatcher.invoke({ parentVT, objectID, parentObjectID, keyNumber, static_cast(keyCode) }); + + // Send response + std::array buffer{ + static_cast(Function::ButtonActivationMessage), + keyCode, + static_cast(objectID), + static_cast(objectID >> 8), + static_cast(parentObjectID), + static_cast(parentObjectID >> 8), + keyNumber, + 0xFF, + }; + if (parentVT->is_vt_version_supported(VTVersion::Version6)) + { + buffer[7] = static_cast(transactionNumber << 4 | 0x0F); + } + CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), + buffer.data(), + CAN_DATA_LENGTH, + parentVT->myControlFunction, + parentVT->partnerControlFunction, + CANIdentifier::CANPriority::Priority5); } } break; @@ -2359,14 +2406,15 @@ namespace isobus std::uint8_t touchState = static_cast(KeyActivationCode::ButtonPressedOrLatched); std::uint16_t parentMaskObjectID = NULL_OBJECT_ID; - if (parentVT->get_vt_version_supported(VTVersion::Version6)) + std::uint8_t transactionNumber = 0xF; + if (parentVT->is_vt_version_supported(VTVersion::Version6)) { - // VT version is at least 6 + // VT version is 6 or later touchState = message.get_uint8_at(5) & 0x0F; + transactionNumber = message.get_uint8_at(5) >> 4; parentMaskObjectID = message.get_uint16_at(6); - //! @todo process TAN } - else if (parentVT->get_vt_version_supported(VTVersion::Version4)) + else if (parentVT->is_vt_version_supported(VTVersion::Version4)) { // VT version is either 4 or 5 touchState = message.get_uint8_at(5); @@ -2376,6 +2424,34 @@ namespace isobus { parentVT->pointingEventDispatcher.invoke({ parentVT, xPosition, yPosition, parentMaskObjectID, static_cast(touchState) }); } + + // Send response + std::array buffer{ + static_cast(Function::PointingEventMessage), + static_cast(xPosition), + static_cast(xPosition >> 8), + static_cast(yPosition), + static_cast(yPosition >> 8), + 0xFF, + 0xFF, + 0xFF, + }; + if (parentVT->is_vt_version_supported(VTVersion::Version6)) + { + // VT version is 6 or later + buffer[5] = static_cast((transactionNumber << 4) | touchState); + } + if (parentVT->is_vt_version_supported(VTVersion::Version4)) + { + // VT version is either 4 or 5 + buffer[5] = touchState; + } + CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), + buffer.data(), + CAN_DATA_LENGTH, + parentVT->myControlFunction, + parentVT->partnerControlFunction, + CANIdentifier::CANPriority::Priority5); } break; @@ -2385,17 +2461,46 @@ namespace isobus bool objectSelected = (0x01 == message.get_uint8_at(3)); bool objectOpenForInput = true; - if (parentVT->get_vt_version_supported(VTVersion::Version4)) + if (parentVT->is_vt_version_supported(VTVersion::Version4)) { objectOpenForInput = message.get_bool_at(4, 0); } - if (parentVT->get_vt_version_supported(VTVersion::Version6)) + std::uint8_t transactionNumber = 0xF; + if (parentVT->is_vt_version_supported(VTVersion::Version6)) { - //! @todo process TAN + transactionNumber = message.get_uint8_at(7) >> 4; } parentVT->selectInputObjectEventDispatcher.invoke({ parentVT, objectID, objectSelected, objectOpenForInput }); + + // Send response + std::array buffer{ + static_cast(Function::VTSelectInputObjectMessage), + static_cast(objectID), + static_cast(objectID >> 8), + static_cast(objectSelected ? 0x01 : 0x00), + 0xFF, + 0xFF, + 0xFF, + 0xFF, + }; + + if (parentVT->is_vt_version_supported(VTVersion::Version4)) + { + buffer[4] = (objectOpenForInput ? 0x01 : 0x00); + } + if (parentVT->is_vt_version_supported(VTVersion::Version6)) + { + buffer[7] = static_cast(transactionNumber << 4 | 0x0F); + } + + CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), + buffer.data(), + CAN_DATA_LENGTH, + parentVT->myControlFunction, + parentVT->partnerControlFunction, + CANIdentifier::CANPriority::Priority5); } break; @@ -2406,12 +2511,32 @@ namespace isobus if ((errorCode == static_cast(ESCMessageErrorCode::OtherError)) || (errorCode <= static_cast(ESCMessageErrorCode::NoInputFieldOpen))) { - if (parentVT->get_vt_version_supported(VTVersion::Version6)) + std::uint8_t transactionNumber = 0xF; + if (parentVT->is_vt_version_supported(VTVersion::Version6)) { - //! @todo process TAN + // VT version is 6 or later + transactionNumber = message.get_uint8_at(7) >> 4; } parentVT->escMessageEventDispatcher.invoke({ parentVT, objectID, static_cast(errorCode) }); + + // Send response + std::array buffer{ + static_cast(Function::VTESCMessage), + static_cast(objectID), + static_cast(objectID >> 8), + 0xFF, + 0xFF, + 0xFF, + 0xFF, + static_cast((transactionNumber << 4) | 0x0F), + }; + CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), + buffer.data(), + CAN_DATA_LENGTH, + parentVT->myControlFunction, + parentVT->partnerControlFunction, + CANIdentifier::CANPriority::Priority5); } } break; @@ -2420,12 +2545,36 @@ namespace isobus { std::uint16_t objectID = message.get_uint16_at(1); std::uint32_t value = message.get_uint32_at(4); - - if (parentVT->get_vt_version_supported(VTVersion::Version6)) + std::uint8_t transactionNumber = 0xF; + if (parentVT->is_vt_version_supported(VTVersion::Version6)) { - //! @todo process TAN + // VT version is 6 or later + transactionNumber = message.get_uint8_at(7) >> 4; } + parentVT->changeNumericValueEventDispatcher.invoke({ parentVT, value, objectID }); + + // Send response + std::array buffer{ + static_cast(Function::VTChangeNumericValueMessage), + static_cast(objectID), + static_cast(objectID >> 8), + 0xFF, + static_cast(value), + static_cast(value >> 8), + static_cast(value >> 16), + static_cast(value >> 24), + }; + if (parentVT->is_vt_version_supported(VTVersion::Version6)) + { + buffer[3] = static_cast(transactionNumber << 4 | 0x0F); + } + CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), + buffer.data(), + CAN_DATA_LENGTH, + parentVT->myControlFunction, + parentVT->partnerControlFunction, + CANIdentifier::CANPriority::Priority5); } break; @@ -2449,6 +2598,24 @@ namespace isobus maskOrChildHasErrors, anyOtherError, poolDeleted }); + + // Send response + std::array buffer{ + static_cast(Function::VTChangeActiveMaskMessage), + static_cast(maskObjectID), + static_cast(maskObjectID >> 8), + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + }; + CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), + buffer.data(), + CAN_DATA_LENGTH, + parentVT->myControlFunction, + parentVT->partnerControlFunction, + CANIdentifier::CANPriority::Priority5); } break; @@ -2469,6 +2636,24 @@ namespace isobus maskOrChildHasErrors, anyOtherError, poolDeleted }); + + // Send response + std::array buffer{ + static_cast(Function::VTChangeSoftKeyMaskMessage), + static_cast(dataOrAlarmMaskID), + static_cast(dataOrAlarmMaskID >> 8), + static_cast(softKeyMaskID), + static_cast(softKeyMaskID >> 8), + 0xFF, + 0xFF, + 0xFF + }; + CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), + buffer.data(), + CAN_DATA_LENGTH, + parentVT->myControlFunction, + parentVT->partnerControlFunction, + CANIdentifier::CANPriority::Priority5); } break; @@ -2479,6 +2664,24 @@ namespace isobus std::string value = std::string(message.get_data().begin() + 4, message.get_data().begin() + 4 + stringLength); parentVT->changeStringValueEventDispatcher.invoke({ value, parentVT, objectID }); + + // Send response + std::array buffer{ + static_cast(Function::VTChangeStringValueMessage), + 0xFF, + 0xFF, + static_cast(objectID), + static_cast(objectID >> 8), + 0xFF, + 0xFF, + 0xFF + }; + CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), + buffer.data(), + CAN_DATA_LENGTH, + parentVT->myControlFunction, + parentVT->partnerControlFunction, + CANIdentifier::CANPriority::Priority5); } break; @@ -2497,10 +2700,26 @@ namespace isobus parentVT->userLayoutHideShowEventDispatcher.invoke({ parentVT, objectID, hidden }); } - if (parentVT->get_vt_version_supported(VTVersion::Version6)) + // Send response + std::array buffer; + std::copy_n(message.get_data().begin(), CAN_DATA_LENGTH, buffer.begin()); + // Make sure we comply with standard specifications + if (parentVT->is_vt_version_supported(VTVersion::Version6)) + { + // VT version is 6 or later + buffer[7] |= 0x0F; + } + else { - //! @todo process TAN + // VT version is 5 or prior + buffer[7] = 0xFF; } + CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), + buffer.data(), + CAN_DATA_LENGTH, + parentVT->myControlFunction, + parentVT->partnerControlFunction, + CANIdentifier::CANPriority::Priority5); } break; @@ -2510,9 +2729,27 @@ namespace isobus parentVT->audioSignalTerminationEventDispatcher.invoke({ parentVT, terminated }); - if (parentVT->get_vt_version_supported(VTVersion::Version6)) + std::uint8_t transactionNumber = 0xF; + if (parentVT->is_vt_version_supported(VTVersion::Version6)) { - //! @todo process TAN + // VT version is 6 or later, send response (VT version 5 and prior does not have a response) + transactionNumber = message.get_uint8_at(2) >> 4; + std::array buffer{ + static_cast(Function::VTControlAudioSignalTerminationMessage), + static_cast(terminated ? 0x01 : 0x00), + static_cast((transactionNumber << 4) | 0x0F), + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + }; + CANNetworkManager::CANNetwork.send_can_message(static_cast(CANLibParameterGroupNumber::ECUtoVirtualTerminal), + buffer.data(), + CAN_DATA_LENGTH, + parentVT->myControlFunction, + parentVT->partnerControlFunction, + CANIdentifier::CANPriority::Priority5); } } break; @@ -2657,7 +2894,7 @@ namespace isobus // bool inputActive = message.get_bool_at(7, 1); // Only in learn mode? // bool controlIsLocked = false; // bool interactionWhileLocked = false; - if (parentVT->get_vt_version_supported(VTVersion::Version6)) + if (parentVT->is_vt_version_supported(VTVersion::Version6)) { // controlIsLocked = message.get_bool_at(7, 2); // interactionWhileLocked = message.get_bool_at(7, 3);