Skip to content

Commit

Permalink
feat(tc): allow deserializing into existing DDOP object in order to e…
Browse files Browse the repository at this point in the history
…xtend it
  • Loading branch information
GwnDaan committed Jan 8, 2025
1 parent 65aa380 commit a8b8da8
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "isobus/isobus/can_NAME.hpp"
#include "isobus/isobus/isobus_task_controller_client_objects.hpp"

#include <functional>
#include <memory>

namespace isobus
Expand Down Expand Up @@ -107,25 +108,43 @@ namespace isobus
std::uint8_t numberDecimals,
std::uint16_t uniqueID);

/// @brief Removes all objects from the DDOP that have a certain type
/// @param objectType The type of object to remove
/// @returns `true` if any objects were removed, `false` if no objects were removed
bool remove_objects_with_type(task_controller_object::ObjectTypes objectType);

/// @brief Removes all objects from the DDOP that have a certain object ID
/// @param objectID The object ID to remove
/// @returns `true` if any objects were removed, `false` if no objects were removed
bool remove_object_with_id(std::uint16_t objectID);

/// @brief Removes all objects from the DDOP that match a certain predicate
/// @param predicate The predicate to match against
/// @returns `true` if any objects were removed, `false` if no objects were removed
bool remove_where(std::function<bool(const task_controller_object::Object &)> predicate);

/// @brief Attempts to take a binary object pool and convert it back into
/// C++ objects. Useful for a task controller server or to view the content
/// C++ objects. The object's will be added to the list of objects,
/// or replaced if an object already exists with the same identifier.
/// of a DDOP captured in a CAN log, for example.
/// @param binaryPool The binary object pool, as an array of bytes.
/// @param clientNAME The ISO NAME of the source ECU for this DDOP, or NAME(0) to ignore checking against actual ECU NAME
/// @returns True if the object pool was successfully deserialized, otherwise false.
/// NOTE: This only means that the pool was deserialized. It does not mean that the
/// @note This only means that the pool was deserialized. It does not mean that the
/// relationship between objects is valid. You may have to do additional
/// checking on the pool before using it.
bool deserialize_binary_object_pool(std::vector<std::uint8_t> &binaryPool, NAME clientNAME = NAME(0));

/// @brief Attempts to take a binary object pool and convert it back into
/// C++ objects. Useful for a task controller server or to view the content
/// C++ objects. The object's will be added to the list of objects,
/// or replaced if an object already exists with the same identifier.
/// Useful for a task controller server or to view the content
/// of a DDOP captured in a CAN log, for example.
/// @param binaryPool The binary object pool, as an array of bytes.
/// @param binaryPoolSizeBytes The size of the DDOP to process in bytes.
/// @param clientNAME The ISO NAME of the source ECU for this DDOP, or NAME(0) to ignore checking against actual ECU NAME
/// @returns True if the object pool was successfully deserialized, otherwise false.
/// NOTE: This only means that the pool was deserialized. It does not mean that the
/// @note This only means that the pool was deserialized. It does not mean that the
/// relationship between objects is valid. You may have to do additional
/// checking on the pool before using it.
bool deserialize_binary_object_pool(const std::uint8_t *binaryPool, std::uint32_t binaryPoolSizeBytes, NAME clientNAME = NAME(0));
Expand Down
35 changes: 34 additions & 1 deletion isobus/src/isobus_device_descriptor_object_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,35 @@ namespace isobus
return retVal;
}

bool DeviceDescriptorObjectPool::remove_objects_with_type(task_controller_object::ObjectTypes objectType)
{
return remove_where([objectType](const task_controller_object::Object &object) { return object.get_object_type() == objectType; });
}

bool DeviceDescriptorObjectPool::remove_object_with_id(std::uint16_t objectID)
{
return remove_where([objectID](const task_controller_object::Object &object) { return object.get_object_id() == objectID; });
}

bool DeviceDescriptorObjectPool::remove_where(std::function<bool(const task_controller_object::Object &)> predicate)
{
bool retVal = false;

for (auto it = objectList.begin(); it != objectList.end();)
{
if (predicate(*(*it)))
{
it = objectList.erase(it);
retVal = true;
}
else
{
++it;
}
}
return retVal;
}

bool DeviceDescriptorObjectPool::deserialize_binary_object_pool(std::vector<std::uint8_t> &binaryPool, NAME clientNAME)
{
return deserialize_binary_object_pool(binaryPool.data(), static_cast<std::uint32_t>(binaryPool.size()), clientNAME);
Expand All @@ -357,7 +386,6 @@ namespace isobus
if ((nullptr != binaryPool) && (0 != binaryPoolSizeBytes))
{
LOG_DEBUG("[DDOP]: Attempting to deserialize a binary object pool with size %u.", binaryPoolSizeBytes);
clear();

// Iterate over the DDOP and convert to objects.
// Using the size to track how much is left to process.
Expand Down Expand Up @@ -489,6 +517,7 @@ namespace isobus
extendedStructureLabel.push_back(binaryPool[31 + numberDeviceSerialNumberBytes + numberDesignatorBytes + numberSoftwareVersionBytes + i]);
}

remove_objects_with_type(task_controller_object::ObjectTypes::Device); // Make sure the previous device object is removed
if (add_device(deviceDesignator, deviceSoftwareVersion, deviceSerialNumber, deviceStructureLabel, localizationLabel, extendedStructureLabel, clientNAME.get_full_name()))
{
binaryPoolSizeBytes -= expectedSize;
Expand Down Expand Up @@ -553,6 +582,7 @@ namespace isobus
deviceElementDesignator.push_back(binaryPool[7 + i]);
}

remove_object_with_id(uniqueID); // Make sure the previous device element object is removed
if (add_device_element(deviceElementDesignator, elementNumber, parentObject, type, uniqueID))
{
auto DETObject = std::static_pointer_cast<task_controller_object::DeviceElementObject>(get_object_by_id(uniqueID));
Expand Down Expand Up @@ -611,6 +641,7 @@ namespace isobus
processDataDesignator.push_back(binaryPool[10 + i]);
}

remove_object_with_id(uniqueID); // Make sure the previous device process data object is removed
if (add_device_process_data(processDataDesignator, DDI, presentationObjectID, binaryPool[7], binaryPool[8], uniqueID))
{
binaryPoolSizeBytes -= expectedSize;
Expand Down Expand Up @@ -661,6 +692,7 @@ namespace isobus
designator.push_back(binaryPool[12 + i]);
}

remove_object_with_id(uniqueID); // Make sure the previous device property object is removed
if (add_device_property(designator, propertyValue, DDI, presentationObjectID, uniqueID))
{
binaryPoolSizeBytes -= expectedSize;
Expand Down Expand Up @@ -723,6 +755,7 @@ namespace isobus
designator.push_back(binaryPool[15 + i]);
}

remove_object_with_id(uniqueID); // Make sure the previous device value presentation object is removed
if (add_device_value_presentation(designator, offset, scale, binaryPool[13], uniqueID))
{
binaryPoolSizeBytes -= expectedSize;
Expand Down

0 comments on commit a8b8da8

Please sign in to comment.