Skip to content
Merged
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
29 changes: 20 additions & 9 deletions isobus/include/isobus/isobus/isobus_virtual_terminal_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,6 @@ namespace isobus
/// @returns true if the message was sent, otherwise false
bool send_change_string_value_message(std::uint16_t objectId, const std::string &value, std::shared_ptr<ControlFunction> destination) const;

/// @brief Sends a response to a load version command
/// The reason this is exposed is because you will need to send this message after
/// the object pool processing thread completes at some point to tell the client to proceed if their
/// object pool was loaded via a load version command.
/// @param[in] errorCodes A set of error bits to report to the client. These will be reported from the managed working set's parsing results.
/// @param[in] destination The VT client to send the message to
/// @returns True if the message was sent, otherwise false
bool send_load_version_response(std::uint8_t errorCodes, std::shared_ptr<ControlFunction> destination) const;

/// @brief Conditionally executes a macro. If the object passed in is of the specified type, and
/// a macro is defined for that object, the macro will be executed if the macro event matches the
/// event ID of the macro.
Expand Down Expand Up @@ -406,6 +397,15 @@ namespace isobus
AnyOtherError = 3
};

/// @brief Enumerates the different error bit indices that can be set in a load version response
enum class LoadVersionErrorBit : std::uint8_t
{
FileSystemErrorOrPoolDataCorruption = 0,
VersionLabelNotCorrectOrUnknown = 1,
InsufficientMemory = 2,
AnyOtherError = 3
};

/// @brief Enumerates the bit indices of the error fields that can be set in a enable/disable object response
enum class EnableDisableObjectErrorBit : std::uint8_t
{
Expand Down Expand Up @@ -818,6 +818,17 @@ namespace isobus
std::uint8_t busyCodesBitfield = 0; ///< The busy codes bitfield
std::uint8_t currentCommandFunctionCode = 0; ///< The current command function code being processed
bool initialized = false; ///< True if the server has been initialized, otherwise false

private:
/// @brief Sends a response to a load version command
/// @param[in] errorCodes A set of error bits to report to the client. These will be reported from the managed working set's parsing results.
/// @param[in] destination The VT client to send the message to
/// @returns True if the message was sent, otherwise false
bool send_load_version_response(std::uint8_t errorCodes, std::shared_ptr<ControlFunction> destination) const;

/// @brief Returns the load version error bitfield to report when a restored object pool fails to parse
/// @returns The file system error or pool data corruption bit, or the any other error bit if our VT version is older than 4
std::uint8_t get_load_version_parse_error_bitfield() const;
};
} // namespace isobus
#endif //ISOBUS_VIRTUAL_TERMINAL_SERVER_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@ namespace isobus
/// which is useful if you want to stop drawing this working set
void clear_callback_handles();

/// @brief Tells the server where this pool originated from.
/// @returns True if this pool was loaded via a Load Version Command, otherwise false (transferred normally)
/// @brief Tells the server whether the pool being parsed must be answered with a Load Version response
/// @returns True from a Load Version Command until the server has sent its Load Version response
bool get_was_object_pool_loaded_from_non_volatile_memory() const;

/// @brief Tells the server where this pool originated from.
/// @param[in] value True if this pool was loaded via a Load Version Command, otherwise false (transferred normally)
/// @brief Tells the server whether the pool being parsed must be answered with a Load Version response
/// @param[in] value True when a Load Version Command restored the pool, false once its Load Version response has been sent
void set_was_object_pool_loaded_from_non_volatile_memory(bool value, CANLibBadge<VirtualTerminalServer>);

/// @brief Sets the object ID of the currently focused object
Expand Down
58 changes: 45 additions & 13 deletions isobus/src/isobus_virtual_terminal_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,19 +554,15 @@
{
managedWorkingSet->set_iop_size(static_cast<std::uint32_t>(loadedVersion.size()));
managedWorkingSet->add_iop_raw_data(loadedVersion);
managedWorkingSet->set_was_object_pool_loaded_from_non_volatile_memory(true, {});
managedWorkingSet->start_parsing_thread();
LOG_DEBUG("[VT Server]: Starting parsing thread for loaded pool data.");
}
else
{
send_load_version_response(0x01, managedWorkingSet->get_control_function());
send_load_version_response(get_bit(static_cast<std::uint8_t>(LoadVersionErrorBit::VersionLabelNotCorrectOrUnknown)), managedWorkingSet->get_control_function());
LOG_ERROR("[VT Server]: Failed to load requested object pool version");
}

if (managedWorkingSet->get_any_object_pools())
{
managedWorkingSet->start_parsing_thread();
managedWorkingSet->set_was_object_pool_loaded_from_non_volatile_memory(true, {});
LOG_DEBUG("[VT Server]: Starting parsing thread for loaded pool data.");
}
}
break;

Expand Down Expand Up @@ -2502,6 +2498,17 @@
return retVal;
}

std::uint8_t VirtualTerminalServer::get_load_version_parse_error_bitfield() const
{
LoadVersionErrorBit errorBit = LoadVersionErrorBit::AnyOtherError;

if (get_vt_version_byte(get_version()) > 3)
{
errorBit = LoadVersionErrorBit::FileSystemErrorOrPoolDataCorruption;
}
return get_bit(static_cast<std::uint8_t>(errorBit));
}

bool VirtualTerminalServer::send_delete_version_response(std::uint8_t errorBitfield, std::shared_ptr<ControlFunction> destination) const
{
bool retVal = false;
Expand Down Expand Up @@ -2808,7 +2815,7 @@
get_priority());
}

void VirtualTerminalServer::update()

Check failure on line 2818 in isobus/src/isobus_virtual_terminal_server.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 28 to the 25 allowed.

See more on https://sonarcloud.io/project/issues?id=ad3154_ISO11783-CAN-Stack&issues=AaEdDtemHOGTnYf8Ld_A&open=AaEdDtemHOGTnYf8Ld_A&pullRequest=766
{
if ((isobus::SystemTiming::time_expired_ms(statusMessageTimestamp_ms, 1000)) &&
(send_status_message()))
Expand All @@ -2826,12 +2833,29 @@

if (nullptr == workingSetObject)
{
LOG_ERROR("[VT Server]: The object pool was parsed but contains no working set object. Rejecting the pool.");
send_end_of_object_pool_response(false, NULL_OBJECT_ID, NULL_OBJECT_ID, get_bit(static_cast<std::uint8_t>(ObjectPoolErrorBit::AnyOtherError)), ws->get_control_function());
if (ws->get_was_object_pool_loaded_from_non_volatile_memory())
{
send_load_version_response(get_load_version_parse_error_bitfield(), ws->get_control_function());
ws->set_was_object_pool_loaded_from_non_volatile_memory(false, {});
LOG_ERROR("[VT Server]: The object pool loaded from non-volatile memory contains no working set object. Rejecting the pool.");
}
else
{
send_end_of_object_pool_response(false, NULL_OBJECT_ID, NULL_OBJECT_ID, get_bit(static_cast<std::uint8_t>(ObjectPoolErrorBit::AnyOtherError)), ws->get_control_function());
LOG_ERROR("[VT Server]: The object pool was parsed but contains no working set object. Rejecting the pool.");
}
}
else
{
send_end_of_object_pool_response(true, NULL_OBJECT_ID, NULL_OBJECT_ID, 0, ws->get_control_function());
if (ws->get_was_object_pool_loaded_from_non_volatile_memory())
{
send_load_version_response(0, ws->get_control_function());
ws->set_was_object_pool_loaded_from_non_volatile_memory(false, {});
}
else
{
send_end_of_object_pool_response(true, NULL_OBJECT_ID, NULL_OBJECT_ID, 0, ws->get_control_function());
}
if (isobus::NULL_CAN_ADDRESS == activeWorkingSetMasterAddress)
{
activeWorkingSetMasterAddress = ws->get_control_function()->get_address();
Expand All @@ -2842,8 +2866,16 @@
else if (VirtualTerminalServerManagedWorkingSet::ObjectPoolProcessingThreadState::Fail == ws->get_object_pool_processing_state())
{
ws->join_parsing_thread();
/// @todo Get the parent object ID of the faulting object
send_end_of_object_pool_response(false, NULL_OBJECT_ID, ws->get_object_pool_faulting_object_id(), get_bit(static_cast<std::uint8_t>(ObjectPoolErrorBit::AnyOtherError)), ws->get_control_function());
if (ws->get_was_object_pool_loaded_from_non_volatile_memory())
{
send_load_version_response(get_load_version_parse_error_bitfield(), ws->get_control_function());
ws->set_was_object_pool_loaded_from_non_volatile_memory(false, {});
}
else
{
/// @todo Get the parent object ID of the faulting object
send_end_of_object_pool_response(false, NULL_OBJECT_ID, ws->get_object_pool_faulting_object_id(), get_bit(static_cast<std::uint8_t>(ObjectPoolErrorBit::AnyOtherError)), ws->get_control_function());
}
}
}
}
Expand Down
Loading
Loading