Skip to content
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

[VT]: Add a way to track VT float attributes #482

Merged
merged 3 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions examples/seeder_example/vt_application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@ bool SeederVtApplication::initialize()

// Track the attribute values we want to update
VTClientUpdateHelper.add_tracked_attribute(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(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();

Expand Down Expand Up @@ -360,7 +360,7 @@ void SeederVtApplication::update()
VTClientUpdateHelper.set_numeric_value(tcSupportedSections_VarNum, TCClientInterface.get_connected_tc_number_sections_supported());
VTClientUpdateHelper.set_numeric_value(tcVersion_VarNum, static_cast<std::uint32_t>(TCClientInterface.get_connected_tc_version()));

if ((0 == speedMessages.get_number_received_machine_selected_speed_command_sources()) &&
if ((0 == speedMessages.get_number_received_machine_selected_speed_sources()) &&
(0 == speedMessages.get_number_received_ground_based_speed_sources()) &&
(0 == speedMessages.get_number_received_wheel_based_speed_sources()))
{
Expand Down Expand Up @@ -688,7 +688,7 @@ void SeederVtApplication::update_alarms()
if (VTClientInterface->get_is_connected() && VTClientUpdateHelper.get_numeric_value(enableAlarms_VarNum))
{
// Check if we have a speed source
if ((0 == speedMessages.get_number_received_machine_selected_speed_command_sources()) &&
if ((0 == speedMessages.get_number_received_machine_selected_speed_sources()) &&
(0 == speedMessages.get_number_received_ground_based_speed_sources()) &&
(0 == speedMessages.get_number_received_wheel_based_speed_sources()))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ namespace isobus
/// @param[in] initialValue The initial value of the attribute to track.
void add_tracked_attribute(std::uint16_t objectId, std::uint8_t attribute, std::uint32_t initialValue = 0);

/// @brief Adds a float attribute to track.
/// @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(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.
/// @param[in] attribute The attribute to remove from tracking.
Expand All @@ -110,6 +116,12 @@ 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 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_as_float(std::uint16_t objectId, std::uint8_t attribute) const;

protected:
std::shared_ptr<ControlFunction> client; ///< The control function of the virtual terminal client to track.
std::shared_ptr<ControlFunction> server; ///< The control function of the server the client is connected to.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,18 @@ namespace isobus
/// @return True if the attribute was set successfully, false otherwise.
bool set_attribute(std::uint16_t objectId, std::uint8_t attribute, std::uint32_t value);

/// @brief Sets the value of a float attribute of a tracked object.
/// @attention ONLY use this function for float attributes defined in ISO11783-6,
/// otherwise you will get incorrect results. Scale on output numbers, for example, is a float.
/// @note If the to be tracked working set consists of more than the master,
/// this function is incompatible with a VT prior to version 4. For working sets consisting
/// of only the master, this function is compatible with any VT version.
/// @param[in] objectId The object id of the attribute to set.
/// @param[in] attribute The attribute to set.
/// @param[in] value The value to set the attribute to.
/// @return True if the attribute was set successfully, false otherwise.
bool set_attribute(std::uint16_t objectId, std::uint8_t attribute, float value);
GwnDaan marked this conversation as resolved.
Show resolved Hide resolved

private:
/// @brief Processes a numeric value change event
/// @param[in] event The numeric value change event to process.
Expand Down
19 changes: 1 addition & 18 deletions isobus/src/isobus_virtual_terminal_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::uint8_t, sizeof(float)> floatBytes = { 0 };
memcpy(floatBytes.data(), &value, sizeof(float));

if (is_big_endian())
{
std::reverse(floatBytes.begin(), floatBytes.end());
}

const std::vector<std::uint8_t> buffer = { static_cast<std::uint8_t>(Function::ChangeAttributeCommand),
static_cast<std::uint8_t>(objectID & 0xFF),
static_cast<std::uint8_t>(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)
Expand Down
11 changes: 11 additions & 0 deletions isobus/src/isobus_virtual_terminal_client_state_tracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <algorithm>

Expand Down Expand Up @@ -160,6 +161,11 @@ namespace isobus
attributeMap[attribute] = initialValue;
}

void VirtualTerminalClientStateTracker::add_tracked_attribute(std::uint16_t objectId, std::uint8_t attribute, float 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)
{
if (attributeStates.find(objectId) == attributeStates.end())
Expand Down Expand Up @@ -196,6 +202,11 @@ namespace isobus
return attributeMap.at(attribute);
}

float VirtualTerminalClientStateTracker::get_attribute_as_float(std::uint16_t objectId, std::uint8_t attribute) const
{
return little_endian_to_float(get_attribute(objectId, attribute));
}

void VirtualTerminalClientStateTracker::cache_active_mask(std::uint16_t maskId)
{
if (activeDataOrAlarmMask != maskId)
Expand Down
14 changes: 10 additions & 4 deletions isobus/src/isobus_virtual_terminal_client_update_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -43,7 +44,7 @@ namespace isobus
}
if (numericValueStates.find(object_id) == numericValueStates.end())
{
LOG_WARNING("[VTStateHelper] set_numeric_value: objectId %lu not tracked", object_id);
LOG_WARNING("[VTStateHelper] set_numeric_value: objectId %hu not tracked", object_id);
return false;
}
if (numericValueStates.at(object_id) == value)
Expand Down Expand Up @@ -126,7 +127,7 @@ namespace isobus
}
if (softKeyMasks.find(maskId) == softKeyMasks.end())
{
LOG_WARNING("[VTStateHelper] set_active_soft_key_mask: data/alarm mask '%lu' not tracked", maskId);
LOG_WARNING("[VTStateHelper] set_active_soft_key_mask: data/alarm mask '%hu' not tracked", maskId);
return false;
}
if (softKeyMasks.at(maskId) == softKeyMaskId)
Expand All @@ -151,12 +152,12 @@ namespace isobus
}
if (attributeStates.find(objectId) == attributeStates.end())
{
LOG_ERROR("[VTStateHelper] set_attribute: objectId %lu not tracked", objectId);
LOG_ERROR("[VTStateHelper] set_attribute: objectId %hu not tracked", objectId);
return false;
}
if (attributeStates.at(objectId).find(attribute) == attributeStates.at(objectId).end())
{
LOG_WARNING("[VTStateHelper] set_attribute: attribute %lu of objectId %lu not tracked", attribute, objectId);
LOG_WARNING("[VTStateHelper] set_attribute: attribute %hhu of objectId %hu not tracked", attribute, objectId);
return false;
}
if (attributeStates.at(objectId).at(attribute) == value)
Expand All @@ -172,4 +173,9 @@ namespace isobus
return success;
}

bool VirtualTerminalClientUpdateHelper::set_attribute(std::uint16_t objectId, std::uint8_t attribute, float value)
{
return set_attribute(objectId, attribute, float_to_little_endian(value));
}

} // namespace isobus
12 changes: 12 additions & 0 deletions utility/include/isobus/utility/platform_endianness.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#ifndef PLATFORM_ENDIANNESS_HPP
#define PLATFORM_ENDIANNESS_HPP

#include <cstdint>

namespace isobus
{
/// @brief Returns if the platform is little endian
Expand All @@ -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
36 changes: 35 additions & 1 deletion utility/src/platform_endianness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "isobus/utility/platform_endianness.hpp"

#include <cstdint>
#include <cstring>

namespace isobus
{
Expand All @@ -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
Loading