Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#ifndef ISOBUS_TASK_CONTROLLER_CLIENT_OBJECTS_HPP
#define ISOBUS_TASK_CONTROLLER_CLIENT_OBJECTS_HPP

#include "isobus/utility/data_span.hpp"

#include <array>
#include <cstdint>
#include <string>
Expand All @@ -22,11 +24,11 @@ namespace isobus
/// @brief Enumerates the different kinds of DDOP objects
enum class ObjectTypes
{
Device, ///< The root object. Each device shall have one single Device
DeviceElement, ///< Subcomponent of a device. Has multiple sub-types
DeviceProcessData, ///< Contains a single process data variable definition
DeviceProperty, ///< A device property element
DeviceValuePresentation ///< Contains the presentation information to display the value of a DeviceProcessData or DeviceProperty object
Device, ///< The root object. Each device shall have one single Device (DVC)
DeviceElement, ///< Subcomponent of a device. Has multiple sub-types (DET)
DeviceProcessData, ///< Contains a single process data variable definition (DPD)
DeviceProperty, ///< A device property element (DPT)
DeviceValuePresentation ///< Contains the presentation information to display the value of a DeviceProcessData or DeviceProperty object (DVP)
};

/// @brief A base class for a Task Controller Object
Expand Down Expand Up @@ -272,6 +274,10 @@ namespace isobus
/// @returns true if the child object ID was found and removed, otherwise false
bool remove_reference_to_child_object(std::uint16_t childID);

/// @brief Returns a span of the child objects added with `add_reference_to_child_object`.
/// @returns A span of the child object IDs
DataSpan<const std::uint16_t> get_child_object_ids() const;

/// @brief Returns the number of child objects added with `add_reference_to_child_object`.
/// @note The maximum number of child objects is technically 65535 because the serialized
/// form of the value uses a 16-bit integer to store the count.
Expand Down Expand Up @@ -368,6 +374,11 @@ namespace isobus
/// @param[in] properties The new properties bitfield to set
void set_properties_bitfield(std::uint8_t properties);

/// @brief Tests whether a property is set in the properties bitfield
/// @param property The property to test for
/// @returns `true` if the property is set, otherwise `false`
bool has_property(DeviceProcessDataObject::PropertiesBit property);

/// @brief Returns the object's available trigger methods
/// @returns The available trigger methods bitfield for this object
std::uint8_t get_trigger_methods_bitfield() const;
Expand All @@ -376,6 +387,11 @@ namespace isobus
/// @param[in] methods The new trigger methods bitfield to set
void set_trigger_methods_bitfield(std::uint8_t methods);

/// @brief Tests whether a trigger method is set in the trigger methods bitfield
/// @param method The trigger method to test for
/// @returns `true` if the trigger method is set, otherwise `false`
bool has_trigger_method(DeviceProcessDataObject::AvailableTriggerMethods method);

private:
static const std::string tableID; ///< XML element namespace for DeviceProcessData.
std::uint16_t ddi; ///< Identifier of process data variable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,22 +260,22 @@ namespace isobus
/// @brief Sends a time interval measurement command.
/// The process data value for this command is the time interval for sending the data element
/// specified by the data dictionary identifier.The client has to send the value of this data
/// element to the TC or DL cyclic with this time interval.
/// element to the TC or DL cyclic with this time interval in milliseconds.
/// @param[in] clientControlFunction The control function to send the message to
/// @param[in] dataDescriptionIndex The data description index of the data element to send the command for
/// @param[in] elementNumber The element number of the data element to send the command for
/// @param[in] timeInterval The time interval for sending the data element specified by the data dictionary identifier.
/// @param[in] timeInterval The time interval in milliseconds for sending the data element specified by the data dictionary identifier.
/// @returns true if the message was sent, otherwise false
bool send_time_interval_measurement_command(std::shared_ptr<ControlFunction> clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t timeInterval) const;

/// @brief Sends a distance interval measurement command.
/// The process data value for this command is the distance interval for sending the data element
/// specified by the data dictionary identifier.The client has to send the value of this data
/// element to the TC or DL cyclic with this distance interval.
/// element to the TC or DL cyclic with this distance interval in millimeters.
/// @param[in] clientControlFunction The control function to send the message to
/// @param[in] dataDescriptionIndex The data description index of the data element to send the command for
/// @param[in] elementNumber The element number of the data element to send the command for
/// @param[in] distanceInterval The distance interval for sending the data element specified by the data dictionary identifier.
/// @param[in] distanceInterval The distance interval in millimeters for sending the data element specified by the data dictionary identifier.
/// @returns true if the message was sent, otherwise false
bool send_distance_interval_measurement_command(std::shared_ptr<ControlFunction> clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t distanceInterval) const;

Expand Down
8 changes: 8 additions & 0 deletions isobus/src/isobus_device_descriptor_object_pool_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,14 @@ namespace isobus
set_value_from_property(retVal.yOffset_mm, property, DataDescriptionIndex::DeviceElementOffsetY);
set_value_from_property(retVal.zOffset_mm, property, DataDescriptionIndex::DeviceElementOffsetZ);
set_value_from_property(retVal.width_mm, property, DataDescriptionIndex::ActualWorkingWidth);
if (!retVal.width_mm.isValuePresent)
{
set_value_from_property(retVal.width_mm, property, DataDescriptionIndex::MaximumWorkingWidth);
}
if (!retVal.width_mm.isValuePresent)
{
set_value_from_property(retVal.width_mm, property, DataDescriptionIndex::DefaultWorkingWidth);
}
}
else if (task_controller_object::ObjectTypes::DeviceProcessData == sectionChildObject->get_object_type())
{
Expand Down
15 changes: 15 additions & 0 deletions isobus/src/isobus_task_controller_client_objects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,11 @@ namespace isobus
return retVal;
}

DataSpan<const std::uint16_t> DeviceElementObject::get_child_object_ids() const
{
return DataSpan<const std::uint16_t>(referenceList.data(), referenceList.size());
}

std::uint16_t DeviceElementObject::get_number_child_objects() const
{
return static_cast<std::uint16_t>(referenceList.size());
Expand Down Expand Up @@ -416,6 +421,11 @@ namespace isobus
propertiesBitfield = properties;
}

bool DeviceProcessDataObject::has_property(DeviceProcessDataObject::PropertiesBit property)
{
return (0 != (propertiesBitfield & static_cast<std::uint8_t>(property)));
}

std::uint8_t DeviceProcessDataObject::get_trigger_methods_bitfield() const
{
return triggerMethodsBitfield;
Expand All @@ -426,6 +436,11 @@ namespace isobus
triggerMethodsBitfield = methods;
}

bool DeviceProcessDataObject::has_trigger_method(DeviceProcessDataObject::AvailableTriggerMethods method)
{
return (0 != (triggerMethodsBitfield & static_cast<std::uint8_t>(method)));
}

const std::string DevicePropertyObject::tableID = "DPT";

DevicePropertyObject::DevicePropertyObject(std::string propertyDesignator,
Expand Down
7 changes: 7 additions & 0 deletions isobus/src/isobus_task_controller_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,36 +61,43 @@ namespace isobus

bool TaskControllerServer::send_time_interval_measurement_command(std::shared_ptr<ControlFunction> clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t timeInterval) const
{
LOG_DEBUG("[TC Server]: Requesting time interval measurement from client %hhu for DDI %s element %hu with time interval %u ms", clientControlFunction->get_address(), DataDictionary::ddi_to_string(dataDescriptionIndex).c_str(), elementNumber, timeInterval);
return send_measurement_command(clientControlFunction, static_cast<std::uint8_t>(ProcessDataCommands::MeasurementTimeInterval), dataDescriptionIndex, elementNumber, timeInterval);
}

bool TaskControllerServer::send_distance_interval_measurement_command(std::shared_ptr<ControlFunction> clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t distanceInterval) const
{
LOG_DEBUG("[TC Server]: Requesting distance interval measurement from client %hhu for DDI %s element %hu with distance interval %u mm", clientControlFunction->get_address(), DataDictionary::ddi_to_string(dataDescriptionIndex).c_str(), elementNumber, distanceInterval);
return send_measurement_command(clientControlFunction, static_cast<std::uint8_t>(ProcessDataCommands::MeasurementDistanceInterval), dataDescriptionIndex, elementNumber, distanceInterval);
}

bool TaskControllerServer::send_minimum_threshold_measurement_command(std::shared_ptr<ControlFunction> clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t minimum) const
{
LOG_DEBUG("[TC Server]: Requesting minimum threshold measurement from client %hhu for DDI %s element %hu with minimum threshold %u", clientControlFunction->get_address(), DataDictionary::ddi_to_string(dataDescriptionIndex).c_str(), elementNumber, minimum);
return send_measurement_command(clientControlFunction, static_cast<std::uint8_t>(ProcessDataCommands::MeasurementMinimumWithinThreshold), dataDescriptionIndex, elementNumber, minimum);
}

bool TaskControllerServer::send_maximum_threshold_measurement_command(std::shared_ptr<ControlFunction> clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t maximum) const
{
LOG_DEBUG("[TC Server]: Requesting maximum threshold measurement from client %hhu for DDI %s element %hu with maximum threshold %u", clientControlFunction->get_address(), DataDictionary::ddi_to_string(dataDescriptionIndex).c_str(), elementNumber, maximum);
return send_measurement_command(clientControlFunction, static_cast<std::uint8_t>(ProcessDataCommands::MeasurementMaximumWithinThreshold), dataDescriptionIndex, elementNumber, maximum);
}

bool TaskControllerServer::send_change_threshold_measurement_command(std::shared_ptr<ControlFunction> clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t threshold) const
{
LOG_DEBUG("[TC Server]: Requesting change threshold measurement from client %hhu for DDI %s element %hu with threshold %u", clientControlFunction->get_address(), DataDictionary::ddi_to_string(dataDescriptionIndex).c_str(), elementNumber, threshold);
return send_measurement_command(clientControlFunction, static_cast<std::uint8_t>(ProcessDataCommands::MeasurementChangeThreshold), dataDescriptionIndex, elementNumber, threshold);
}

bool TaskControllerServer::send_set_value_and_acknowledge(std::shared_ptr<ControlFunction> clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t processDataValue) const
{
LOG_DEBUG("[TC Server]: Sending set value and acknowledge to client %hhu for DDI %s element %hu with value %s", clientControlFunction->get_address(), DataDictionary::ddi_to_string(dataDescriptionIndex).c_str(), elementNumber, DataDictionary::format_value_with_ddi(dataDescriptionIndex, processDataValue).c_str());
return send_measurement_command(clientControlFunction, static_cast<std::uint8_t>(ProcessDataCommands::SetValueAndAcknowledge), dataDescriptionIndex, elementNumber, processDataValue);
}

bool TaskControllerServer::send_set_value(std::shared_ptr<ControlFunction> clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t processDataValue) const
{
LOG_DEBUG("[TC Server]: Sending set value to client %hhu for DDI %s element %hu with value %s", clientControlFunction->get_address(), DataDictionary::ddi_to_string(dataDescriptionIndex).c_str(), elementNumber, DataDictionary::format_value_with_ddi(dataDescriptionIndex, processDataValue).c_str());
return send_measurement_command(clientControlFunction, static_cast<std::uint8_t>(ProcessDataCommands::Value), dataDescriptionIndex, elementNumber, processDataValue);
}

Expand Down
Loading