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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion examples/seeder_example/vt_application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ bool SeederVtApplication::initialize()
VTClientUpdateHelper.add_tracked_numeric_value(currentAlarms2_ObjPtr);

// Track the attribute values we want to update
VTClientUpdateHelper.add_tracked_attribute(speed_OutNum, 8, 0.0036f);
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);
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_float(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, if you tracked it with add_tracked_attribute_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;

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 All @@ -134,6 +146,7 @@ namespace isobus
std::uint8_t activeWorkingSetAddress = NULL_CAN_ADDRESS; ///< Holds the address of the control function that currently has
std::map<std::uint16_t, std::uint16_t> softKeyMasks; ///< Holds the data/alarms masks with their associated soft keys masks for tracked objects.
std::map<std::uint16_t, std::map<std::uint8_t, std::uint32_t>> attributeStates; ///< Holds the 'attribute' state of tracked objects.
std::map<std::uint16_t, std::map<std::uint8_t, float>> floatAttributeStates; ///< Holds the 'attribute' state of tracked objects, for attributes that use floats (scale, for example).
//! TODO: std::map<std::uint16_t, std::uint8_t> alarmMaskPrioritiesStates; ///< Holds the 'alarm mask priority' state of tracked objects.
//! TODO: std::map<std::uint16_t, std::pair<std::uint8_t, std::uint16_t>> listItemStates; ///< Holds the 'list item' state of tracked objects.
//! TODO: add lock/unlock mask state
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);
Comment on lines +77 to +87
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: hmm, seems a lot of duplication that we might be able to avoid? With your current implementation we leave the conversion from float value to uint32_t all the way up to the VT client. What if we instead do it in this function directly? And then call the neighbor helper set_attribute function instead

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm good idea I think, that does sound appealing. I can rework it


private:
/// @brief Processes a numeric value change event
/// @param[in] event The numeric value change event to process.
Expand Down
49 changes: 49 additions & 0 deletions isobus/src/isobus_virtual_terminal_client_state_tracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,24 @@ namespace isobus
attributeMap[attribute] = initialValue;
}

void VirtualTerminalClientStateTracker::add_tracked_attribute_float(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;
}

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 +214,37 @@ namespace isobus
return attributeMap.at(attribute);
}

float VirtualTerminalClientStateTracker::get_attribute_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<float>(attributeMap.at(attribute));
}
}
return 0.0f;
}

void VirtualTerminalClientStateTracker::cache_active_mask(std::uint16_t maskId)
{
if (activeDataOrAlarmMask != maskId)
Expand Down
30 changes: 30 additions & 0 deletions isobus/src/isobus_virtual_terminal_client_update_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,34 @@ namespace isobus
return success;
}

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;
}

} // namespace isobus
Loading