Skip to content

Commit

Permalink
[VT]: Add a way to track VT float attributes
Browse files Browse the repository at this point in the history
This lets you use the VT state helper to deal with float attributes.
Previously, float values may not have been handled correctly.
  • Loading branch information
ad3154 committed Jul 9, 2024
1 parent b2dd3bb commit 4c83485
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 1 deletion.
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);

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

0 comments on commit 4c83485

Please sign in to comment.