Skip to content

Commit

Permalink
[VT]: Add VT server implementation of change polygon point and delete…
Browse files Browse the repository at this point in the history
… object pool

Added the ability to change output polygons' point information in the VT objects.
Added VT server support for change polygon point messages.
Added VT server support for delete object pool messages.
  • Loading branch information
ad3154 committed Sep 26, 2024
1 parent 9fcea25 commit 5f3df7d
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2506,6 +2506,13 @@ namespace isobus
/// @returns A point in the polygon by index, or zeros if the index is out of range.
PolygonPoint get_point(std::uint8_t index);

/// @brief Changes a polygon point by index
/// @param[in] index The point index to modify
/// @param[in] x The new X position of the point, relative to the top left corner of the polygon
/// @param[in] y The new Y position of the point, relative to the top left corner of the polygon
/// @returns True if the point was modified, false if the index was out of range
bool change_point(std::uint8_t index, std::uint16_t x, std::uint16_t y);

/// @brief Returns the polygon type of this object
/// @returns The polygon type of this object
PolygonType get_type() const;
Expand Down
37 changes: 37 additions & 0 deletions isobus/include/isobus/isobus/isobus_virtual_terminal_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,16 @@ namespace isobus
/// @returns True if all relevant object pools were deleted from VT non-volatile storage, otherwise false.
virtual bool delete_all_versions(NAME clientNAME) = 0;

/// @brief This function is called when the client wants the server to deactivate its object pool.
/// You should treat this as a disconnection by the client, as it may be moving to another VT.
/// @attention This does not mean to delete the pool from non-volatile memory!!! This only deactivates the active pool.
/// @details This command is used to delete the entire object pool of this Working Set from volatile storage.
/// This command can be used by an implement when it wants to move its object pool to another VT,
/// or when it is shutting down or during the development of object pools.
/// @param[in] clientNAME The NAME of the client that is requesting deletion
/// @returns True if the client's active object pool was deactivated and removed from volatile storage, otherwise false.
virtual bool delete_object_pool(NAME clientNAME) = 0;

//------------ Optional functions you can override --------------------
virtual VirtualTerminalBase::GraphicMode get_graphic_mode() const;
virtual std::uint8_t get_powerup_time() const;
Expand Down Expand Up @@ -345,6 +355,20 @@ namespace isobus
ObjectIsOpenedForEdit = 2 // VT version 4 and later
};

/// @brief Enumerates the bit indices of the error fields that can be set in a change polygon point response
enum class ChangePolygonPointErrorBit : std::uint8_t
{
InvalidObjectID = 0,
InvalidPointIndex = 1,
AnyOtherError = 2
};

enum class DeleteObjectPoolErrorBit : std::uint8_t
{
DeletionError = 0,
AnyOtherError = 8
};

/// @brief Checks to see if the message should be listened to based on
/// what the message is, and if the client has sent the proper working set master message
bool check_if_source_is_managed(const CANMessage &message);
Expand Down Expand Up @@ -454,6 +478,13 @@ namespace isobus
/// @returns true if the message was sent, otherwise false
bool send_change_numeric_value_response(std::uint16_t objectID, std::uint8_t errorBitfield, std::uint32_t value, std::shared_ptr<ControlFunction> destination);

/// @brief Sends a response to a change polygon point command
/// @param[in] objectID The object ID of the modified polygon
/// @param[in] errorBitfield An error bitfield
/// @param[in] destination The control function to send the message to
/// @returns true if the message was sent, otherwise false
bool send_change_polygon_point_response(std::uint16_t objectID, std::uint8_t errorBitfield, std::shared_ptr<ControlFunction> destination);

/// @brief Sends a response to a change size command
/// @param[in] objectID The object ID for the object whose size was meant to be changed
/// @param[in] errorBitfield An error bitfield
Expand Down Expand Up @@ -482,6 +513,12 @@ namespace isobus
/// @returns True if the message was sent, otherwise false
bool send_delete_version_response(std::uint8_t errorBitfield, std::shared_ptr<ControlFunction> destination) const;

/// @brief Sends a response to a delete object pool command
/// @param[in] errorBitfield An error bitfield to report back to the client
/// @param[in] destination The control function to send the message to
/// @returns True if the message was sent, otherwise false
bool send_delete_object_pool_response(std::uint8_t errorBitfield, std::shared_ptr<ControlFunction> destination) const;

/// @brief Sends a response to the enable/disable object command
/// @param[in] objectID The object ID for the object
/// @param[in] errorBitfield An error bitfield
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@ namespace isobus
/// @returns The timestamp for when we received the last auxiliary input maintenance message
std::uint32_t get_auxiliary_input_maintenance_timestamp_ms() const;

/// @brief Marks the working set for deletion/deactivation by the server.
/// The server will call this when object pool deletion is requested for this working set
/// by the appropriate working set master.
void request_deletion();

/// @brief Returns if the server has marked this working set for deletion
/// @returns true if the working set should be deleted, otherwise false
bool is_deletion_requested() const;

private:
/// @brief Adds an object to the object tree, and replaces an object of the same type
/// if there's already one in the tree with the same ID.
Expand Down Expand Up @@ -168,6 +177,7 @@ namespace isobus
std::uint16_t faultingObjectID = NULL_OBJECT_ID; ///< Stores the faulting object ID to send to a client when parsing the pool fails
std::uint16_t focusedObject = NULL_OBJECT_ID; ///< Stores the object ID of the currently focused object
bool wasLoadedFromNonVolatileMemory = false; ///< Used to tell the server how this object pool was obtained
bool workingSetDeletionRequested = false;
};
} // namespace isobus

Expand Down
13 changes: 13 additions & 0 deletions isobus/src/isobus_virtual_terminal_objects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4933,6 +4933,19 @@ namespace isobus
return retVal;
}

bool OutputPolygon::change_point(std::uint8_t index, std::uint16_t x, std::uint16_t y)
{
bool retVal = false;

if (index < pointList.size())
{
pointList.at(index).xValue = x;
pointList.at(index).yValue = y;
retVal = true;
}
return retVal;
}

OutputPolygon::PolygonType OutputPolygon::get_type() const
{
return static_cast<PolygonType>(polygonType);
Expand Down
108 changes: 108 additions & 0 deletions isobus/src/isobus_virtual_terminal_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1643,6 +1643,61 @@ namespace isobus
}
break;

case Function::DeleteObjectPoolCommand:
{
CANStackLogger::info("[VT Server]: Client %u requests deletion of object pool from volatile memory.", cf->get_control_function()->get_address());
if (parentServer->delete_object_pool(cf->get_control_function()->get_NAME()))
{
CANStackLogger::info("[VT Server]: Client %u object pool has been deactivated.", cf->get_control_function()->get_address());
parentServer->send_delete_object_pool_response(0, message.get_source_control_function());
}
else
{
CANStackLogger::error("[VT Server]: Client %u object pool failed to be deactivated.", cf->get_control_function()->get_address());
parentServer->send_delete_object_pool_response((1 << static_cast<std::uint8_t>(DeleteObjectPoolErrorBit::DeletionError)), message.get_source_control_function());
}
}
break;

case Function::ChangePolygonPointCommand:
{
auto objectID = static_cast<std::uint16_t>(static_cast<std::uint16_t>(data[1]) | (static_cast<std::uint16_t>(data[2]) << 8));
const std::uint8_t polygonPointIndex = data[3];
const std::uint16_t newXValue = static_cast<std::uint16_t>(static_cast<std::uint16_t>(data[4]) | (static_cast<std::uint16_t>(data[5]) << 8));
const std::uint16_t newYValue = static_cast<std::uint16_t>(static_cast<std::uint16_t>(data[6]) | (static_cast<std::uint16_t>(data[7]) << 8));
auto targetObject = cf->get_object_by_id(objectID);

if (nullptr != targetObject)
{
if (VirtualTerminalObjectType::OutputPolygon == targetObject->get_object_type())
{
auto polygon = std::static_pointer_cast<OutputPolygon>(targetObject);

if (polygon->change_point(polygonPointIndex, newXValue, newYValue))
{
CANStackLogger::debug("[VT Server]: Client %u change polygon id %u point index %u. X = %u, Y = %u", cf->get_control_function()->get_address(), objectID, polygonPointIndex, newXValue, newYValue);
parentServer->send_change_polygon_point_response(objectID, 0, message.get_source_control_function());
}
else
{
CANStackLogger::warn("[VT Server]: Client %u change polygon point: the point index of %u is not valid for object %u", cf->get_control_function()->get_address(), polygonPointIndex, objectID);
parentServer->send_change_polygon_point_response(objectID, (1 << static_cast<std::uint8_t>(ChangePolygonPointErrorBit::InvalidPointIndex)), message.get_source_control_function());
}
}
else
{
CANStackLogger::warn("[VT Server]: Client %u change polygon point: object id %u is not an output polygon", cf->get_control_function()->get_address(), objectID);
parentServer->send_change_polygon_point_response(objectID, (1 << static_cast<std::uint8_t>(ChangePolygonPointErrorBit::AnyOtherError)), message.get_source_control_function());
}
}
else
{
CANStackLogger::warn("[VT Server]: Client %u change polygon point: invalid object ID of %u", cf->get_control_function()->get_address(), objectID);
parentServer->send_change_polygon_point_response(objectID, (1 << static_cast<std::uint8_t>(ChangePolygonPointErrorBit::InvalidObjectID)), message.get_source_control_function());
}
}
break;

case Function::ButtonActivationMessage:
case Function::SoftKeyActivationMessage:
case Function::PointingEventMessage:
Expand Down Expand Up @@ -2136,6 +2191,33 @@ namespace isobus
return retVal;
}

bool VirtualTerminalServer::send_change_polygon_point_response(std::uint16_t objectID, std::uint8_t errorBitfield, std::shared_ptr<ControlFunction> destination)
{
bool retVal = false;

if (nullptr != destination)
{
std::array<std::uint8_t, CAN_DATA_LENGTH> buffer;

buffer[0] = static_cast<std::uint8_t>(Function::ChangePolygonPointCommand);
buffer[1] = static_cast<std::uint8_t>(objectID & 0xFF);
buffer[2] = static_cast<std::uint8_t>(objectID >> 8);
buffer[3] = errorBitfield;
buffer[4] = 0xFF;
buffer[5] = 0xFF;
buffer[6] = 0xFF;
buffer[7] = 0xFF;

retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast<std::uint32_t>(CANLibParameterGroupNumber::VirtualTerminalToECU),
buffer.data(),
CAN_DATA_LENGTH,
serverInternalControlFunction,
destination,
get_priority());
}
return retVal;
}

bool VirtualTerminalServer::send_change_size_response(std::uint16_t objectID, std::uint8_t errorBitfield, std::shared_ptr<ControlFunction> destination)
{
bool retVal = false;
Expand Down Expand Up @@ -2242,6 +2324,32 @@ namespace isobus
return retVal;
}

bool VirtualTerminalServer::send_delete_object_pool_response(std::uint8_t errorBitfield, std::shared_ptr<ControlFunction> destination) const
{
bool retVal = false;

if (nullptr != destination)
{
const std::array<std::uint8_t, CAN_DATA_LENGTH> buffer = {
static_cast<std::uint8_t>(Function::DeleteObjectPoolCommand),
errorBitfield,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF
};
retVal = CANNetworkManager::CANNetwork.send_can_message(static_cast<std::uint32_t>(CANLibParameterGroupNumber::VirtualTerminalToECU),
buffer.data(),
CAN_DATA_LENGTH,
serverInternalControlFunction,
destination,
get_priority());
}
return retVal;
}

bool VirtualTerminalServer::send_enable_disable_object_response(std::uint16_t objectID, std::uint8_t errorBitfield, bool value, std::shared_ptr<ControlFunction> destination)
{
bool retVal = false;
Expand Down
10 changes: 10 additions & 0 deletions isobus/src/isobus_virtual_terminal_server_managed_working_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,16 @@ namespace isobus
return auxiliaryInputMaintenanceMessageTimestamp_ms;
}

void VirtualTerminalServerManagedWorkingSet::request_deletion()
{
workingSetDeletionRequested = true;
}

bool VirtualTerminalServerManagedWorkingSet::is_deletion_requested() const
{
return workingSetDeletionRequested;
}

bool VirtualTerminalServerManagedWorkingSet::add_or_replace_object(std::shared_ptr<VTObject> objectToAdd)
{
bool retVal = false;
Expand Down

0 comments on commit 5f3df7d

Please sign in to comment.