diff --git a/examples/seeder_example/vt_application.cpp b/examples/seeder_example/vt_application.cpp index b8d7898f..70f41465 100644 --- a/examples/seeder_example/vt_application.cpp +++ b/examples/seeder_example/vt_application.cpp @@ -76,13 +76,13 @@ bool SeederVtApplication::initialize() VTClientUpdateHelper.add_tracked_numeric_value(currentAlarms2_ObjPtr); // Track the attribute values we want to update - VTClientUpdateHelper.add_tracked_attribute_float(speed_OutNum, 8, 0.0036f); - VTClientUpdateHelper.add_tracked_attribute(section1Status_OutRect, 5, solidGreen_FillAttr); - VTClientUpdateHelper.add_tracked_attribute(section2Status_OutRect, 5, solidYellow_FillAttr); - VTClientUpdateHelper.add_tracked_attribute(section3Status_OutRect, 5, solidRed_FillAttr); - VTClientUpdateHelper.add_tracked_attribute(section4Status_OutRect, 5, solidRed_FillAttr); - VTClientUpdateHelper.add_tracked_attribute(section5Status_OutRect, 5, solidYellow_FillAttr); - VTClientUpdateHelper.add_tracked_attribute(section6Status_OutRect, 5, solidGreen_FillAttr); + VTClientUpdateHelper.add_tracked_attribute(speed_OutNum, 8, 0.0036f); + VTClientUpdateHelper.add_tracked_attribute(section1Status_OutRect, 5, (std::uint32_t)solidGreen_FillAttr); + VTClientUpdateHelper.add_tracked_attribute(section2Status_OutRect, 5, (std::uint32_t)solidYellow_FillAttr); + VTClientUpdateHelper.add_tracked_attribute(section3Status_OutRect, 5, (std::uint32_t)solidRed_FillAttr); + VTClientUpdateHelper.add_tracked_attribute(section4Status_OutRect, 5, (std::uint32_t)solidRed_FillAttr); + VTClientUpdateHelper.add_tracked_attribute(section5Status_OutRect, 5, (std::uint32_t)solidYellow_FillAttr); + VTClientUpdateHelper.add_tracked_attribute(section6Status_OutRect, 5, (std::uint32_t)solidGreen_FillAttr); VTClientUpdateHelper.initialize(); diff --git a/isobus/include/isobus/isobus/isobus_virtual_terminal_client_state_tracker.hpp b/isobus/include/isobus/isobus/isobus_virtual_terminal_client_state_tracker.hpp index 543f2b8e..3e25fa5c 100644 --- a/isobus/include/isobus/isobus/isobus_virtual_terminal_client_state_tracker.hpp +++ b/isobus/include/isobus/isobus/isobus_virtual_terminal_client_state_tracker.hpp @@ -103,7 +103,7 @@ namespace isobus /// @param[in] objectId The object id of the attribute to track. /// @param[in] attribute The attribute to track. Make sure it's a float attribute! /// @param[in] initialValue The initial value of the attribute to track. - void add_tracked_attribute_float(std::uint16_t objectId, std::uint8_t attribute, float initialValue = 0.0f); + void add_tracked_attribute(std::uint16_t objectId, std::uint8_t attribute, float initialValue = 0.0f); /// @brief Removes an attribute from tracking. /// @param[in] objectId The object id of the attribute to remove from tracking. @@ -116,11 +116,11 @@ namespace isobus /// @return The value of the attribute of the tracked object. std::uint32_t get_attribute(std::uint16_t objectId, std::uint8_t attribute) const; - /// @brief Get the value of an attribute of a tracked object, if you tracked it with add_tracked_attribute_float. + /// @brief Get the value of an attribute of a tracked object as a float. /// @param[in] objectId The object id of the attribute to get. /// @param[in] attribute The attribute to get. /// @return The value of the attribute of the tracked object. - float get_attribute_float(std::uint16_t objectId, std::uint8_t attribute) const; + float get_attribute_as_float(std::uint16_t objectId, std::uint8_t attribute) const; protected: std::shared_ptr client; ///< The control function of the virtual terminal client to track. @@ -146,7 +146,6 @@ namespace isobus std::uint8_t activeWorkingSetAddress = NULL_CAN_ADDRESS; ///< Holds the address of the control function that currently has std::map softKeyMasks; ///< Holds the data/alarms masks with their associated soft keys masks for tracked objects. std::map> attributeStates; ///< Holds the 'attribute' state of tracked objects. - std::map> floatAttributeStates; ///< Holds the 'attribute' state of tracked objects, for attributes that use floats (scale, for example). //! TODO: std::map alarmMaskPrioritiesStates; ///< Holds the 'alarm mask priority' state of tracked objects. //! TODO: std::map> listItemStates; ///< Holds the 'list item' state of tracked objects. //! TODO: add lock/unlock mask state diff --git a/isobus/src/isobus_virtual_terminal_client.cpp b/isobus/src/isobus_virtual_terminal_client.cpp index 23282c0e..67bd1981 100644 --- a/isobus/src/isobus_virtual_terminal_client.cpp +++ b/isobus/src/isobus_virtual_terminal_client.cpp @@ -545,24 +545,7 @@ namespace isobus bool VirtualTerminalClient::send_change_attribute(std::uint16_t objectID, std::uint8_t attributeID, float value) { - static_assert(sizeof(float) == 4, "Float must be 4 bytes"); - std::array floatBytes = { 0 }; - memcpy(floatBytes.data(), &value, sizeof(float)); - - if (is_big_endian()) - { - std::reverse(floatBytes.begin(), floatBytes.end()); - } - - const std::vector buffer = { static_cast(Function::ChangeAttributeCommand), - static_cast(objectID & 0xFF), - static_cast(objectID >> 8), - attributeID, - floatBytes[0], - floatBytes[1], - floatBytes[2], - floatBytes[3] }; - return queue_command(buffer); + return send_change_attribute(objectID, attributeID, float_to_little_endian(value)); } bool VirtualTerminalClient::send_change_priority(std::uint16_t alarmMaskObjectID, AlarmMaskPriority priority) diff --git a/isobus/src/isobus_virtual_terminal_client_state_tracker.cpp b/isobus/src/isobus_virtual_terminal_client_state_tracker.cpp index 974509ef..435609f5 100644 --- a/isobus/src/isobus_virtual_terminal_client_state_tracker.cpp +++ b/isobus/src/isobus_virtual_terminal_client_state_tracker.cpp @@ -12,6 +12,7 @@ #include "isobus/isobus/can_network_manager.hpp" #include "isobus/isobus/can_stack_logger.hpp" #include "isobus/isobus/isobus_virtual_terminal_client.hpp" +#include "isobus/utility/platform_endianness.hpp" #include @@ -160,22 +161,9 @@ namespace isobus attributeMap[attribute] = initialValue; } - void VirtualTerminalClientStateTracker::add_tracked_attribute_float(std::uint16_t objectId, std::uint8_t attribute, float initialValue) + void VirtualTerminalClientStateTracker::add_tracked_attribute(std::uint16_t objectId, std::uint8_t attribute, float initialValue) { - if (floatAttributeStates.find(objectId) == floatAttributeStates.end()) - { - floatAttributeStates[objectId] = {}; - } - - auto &attributeMap = floatAttributeStates.at(objectId); - if ((attributeMap.find(attribute) != attributeMap.end()) || - (floatAttributeStates.find(attribute) != floatAttributeStates.end())) - { - LOG_WARNING("[VTStateHelper] add_tracked_attribute: attribute '%lu' of objectId '%lu' already tracked", attribute, objectId); - return; - } - - attributeMap[attribute] = initialValue; + return add_tracked_attribute(objectId, attribute, float_to_little_endian(initialValue)); } void VirtualTerminalClientStateTracker::remove_tracked_attribute(std::uint16_t objectId, std::uint8_t attribute) @@ -214,35 +202,9 @@ namespace isobus return attributeMap.at(attribute); } - float VirtualTerminalClientStateTracker::get_attribute_float(std::uint16_t objectId, std::uint8_t attribute) const + float VirtualTerminalClientStateTracker::get_attribute_as_float(std::uint16_t objectId, std::uint8_t attribute) const { - if (attributeStates.find(objectId) == attributeStates.end()) - { - if (floatAttributeStates.find(objectId) == floatAttributeStates.end()) - { - LOG_WARNING("[VTStateHelper] get_attribute_float: objectId '%lu' has no tracked float attributes", objectId); - return 0.0f; - } - - const auto &floatAttributeMap = floatAttributeStates.at(objectId); - if (floatAttributeStates.find(attribute) == floatAttributeStates.end()) - { - LOG_WARNING("[VTStateHelper] get_attribute_float: float attribute '%lu' of objectId '%lu' not tracked", attribute, objectId); - return 0; - } - return floatAttributeMap.at(attribute); - } - else - { - const auto &attributeMap = attributeStates.at(objectId); - - if (attributeMap.find(attribute) != attributeMap.end()) - { - LOG_WARNING("[VTStateHelper] get_attribute_float: attribute '%lu' of objectId '%lu' was tracked as an integer. You are calling the wrong function to get its value!", attribute, objectId); - return static_cast(attributeMap.at(attribute)); - } - } - return 0.0f; + return little_endian_to_float(get_attribute(objectId, attribute)); } void VirtualTerminalClientStateTracker::cache_active_mask(std::uint16_t maskId) diff --git a/isobus/src/isobus_virtual_terminal_client_update_helper.cpp b/isobus/src/isobus_virtual_terminal_client_update_helper.cpp index 34842cf4..e6cf653b 100644 --- a/isobus/src/isobus_virtual_terminal_client_update_helper.cpp +++ b/isobus/src/isobus_virtual_terminal_client_update_helper.cpp @@ -10,6 +10,7 @@ #include "isobus/isobus/isobus_virtual_terminal_client_update_helper.hpp" #include "isobus/isobus/can_stack_logger.hpp" +#include "isobus/utility/platform_endianness.hpp" namespace isobus { @@ -174,32 +175,7 @@ namespace isobus bool VirtualTerminalClientUpdateHelper::set_attribute(std::uint16_t objectId, std::uint8_t attribute, float value) { - if (nullptr == client) - { - LOG_ERROR("[VTStateHelper] set_attribute: client is nullptr"); - return false; - } - if (floatAttributeStates.find(objectId) == floatAttributeStates.end()) - { - LOG_ERROR("[VTStateHelper] set_attribute: objectId %lu has no float attributes tracked", objectId); - return false; - } - if (floatAttributeStates.at(objectId).find(attribute) == floatAttributeStates.at(objectId).end()) - { - LOG_WARNING("[VTStateHelper] set_attribute: float attribute %lu of objectId %lu not tracked", attribute, objectId); - return false; - } - if (floatAttributeStates.at(objectId).at(attribute) == value) - { - return true; - } - - bool success = vtClient->send_change_attribute(objectId, attribute, value); - if (success) - { - floatAttributeStates[objectId][attribute] = value; - } - return success; + return set_attribute(objectId, attribute, float_to_little_endian(value)); } } // namespace isobus diff --git a/utility/include/isobus/utility/platform_endianness.hpp b/utility/include/isobus/utility/platform_endianness.hpp index 7c33f3b2..9e4fc77c 100644 --- a/utility/include/isobus/utility/platform_endianness.hpp +++ b/utility/include/isobus/utility/platform_endianness.hpp @@ -10,6 +10,8 @@ #ifndef PLATFORM_ENDIANNESS_HPP #define PLATFORM_ENDIANNESS_HPP +#include + namespace isobus { /// @brief Returns if the platform is little endian @@ -20,6 +22,16 @@ namespace isobus /// @returns `true` if the platform is big endian, otherwise false bool is_big_endian(); + /// @brief Convert a float attribute to a little endian byte representation + /// @param[in] value The float value to convert + /// @returns The float value as a little endian byte representation + std::uint32_t float_to_little_endian(float value); + + /// @brief Convert a little endian byte representation to a float attribute + /// @param[in] byteRepresentation The little endian byte representation to convert + /// @returns The float value + float little_endian_to_float(std::uint32_t byteRepresentation); + } // namespace isobus #endif //PLATFORM_ENDIANNESS_HPP diff --git a/utility/src/platform_endianness.cpp b/utility/src/platform_endianness.cpp index 6e75582d..09bbe68f 100644 --- a/utility/src/platform_endianness.cpp +++ b/utility/src/platform_endianness.cpp @@ -10,6 +10,7 @@ #include "isobus/utility/platform_endianness.hpp" #include +#include namespace isobus { @@ -24,4 +25,37 @@ namespace isobus { return (false == is_little_endian()); } -} // namespace isobus + + std::uint32_t float_to_little_endian(float value) + { + static_assert(sizeof(float) == 4, "Float must be 4 bytes"); + std::uint32_t byteRepresentation; + std::memcpy(&byteRepresentation, &value, sizeof(float)); + if (is_big_endian()) + { + byteRepresentation = + ((byteRepresentation & 0x000000FF) << 24) | + ((byteRepresentation & 0x0000FF00) << 8) | + ((byteRepresentation & 0x00FF0000) >> 8) | + ((byteRepresentation & 0xFF000000) >> 24); + } + return byteRepresentation; + } + + float little_endian_to_float(std::uint32_t byteRepresentation) + { + static_assert(sizeof(float) == 4, "Float must be 4 bytes"); + if (is_big_endian()) + { + byteRepresentation = + ((byteRepresentation & 0x000000FF) << 24) | + ((byteRepresentation & 0x0000FF00) << 8) | + ((byteRepresentation & 0x00FF0000) >> 8) | + ((byteRepresentation & 0xFF000000) >> 24); + } + float value; + std::memcpy(&value, &byteRepresentation, sizeof(float)); + return value; + } +} +// namespace isobus