20#include "isobus/utility/system_timing.hpp"
27 std::unique_ptr<CANMessageData> data,
28 std::uint32_t parameterGroupNumber,
29 std::uint16_t totalMessageSize,
30 std::uint8_t sequenceNumber,
32 std::shared_ptr<ControlFunction> source,
33 std::shared_ptr<ControlFunction> destination,
35 void *parentPointer) :
36 TransportProtocolSessionBase(direction, std::move(data), parameterGroupNumber, totalMessageSize, source, destination, sessionCompleteCallback, parentPointer),
37 sequenceNumber(sequenceNumber),
50 return (
nullptr == get_destination());
55 return numberOfBytesTransferred;
62 if (numberOfFrames > 0)
64 return numberOfFrames;
74 return get_total_number_of_packets() - get_last_packet_number();
84 numberOfBytesTransferred += bytes;
90 std::uint8_t numberOfFrames = 0;
92 if (messageLength > 6)
102 return numberOfFrames;
131 const std::uint8_t *messageData,
132 std::uint8_t messageLength,
133 std::shared_ptr<InternalControlFunction> source,
134 std::shared_ptr<ControlFunction> destination,
140 std::unique_ptr<CANMessageData> data;
141 if (
nullptr != frameChunkCallback)
145 else if (
nullptr != messageData)
154 LOG_ERROR(
"[FP]: Unable to send multipacket message, data is invalid or has invalid length.");
157 else if ((
nullptr == source) || (!source->get_address_valid()) ||
has_session(parameterGroupNumber, source, destination))
159 LOG_ERROR(
"[FP]: Unable to send multipacket message, source is invalid or already in a session for the PGN.");
164 LOG_ERROR(
"[FP]: Unable to send multipacket message, PGN is unsupported by this protocol.");
167 else if ((
nullptr != destination) && (!destination->get_address_valid()))
169 LOG_ERROR(
"[FP]: Unable to send multipacket message, destination is invalid.");
176 parameterGroupNumber,
197 if (!session->get_source()->get_address_valid())
199 LOG_WARNING(
"[FP]: Closing active session as the source control function is no longer valid");
202 else if (!session->is_broadcast() && !session->get_destination()->get_address_valid())
204 LOG_WARNING(
"[FP]: Closing active session as the destination control function is no longer valid");
213 if (
nullptr != session)
215 bool formerSessionMatched =
false;
219 if ((formerSessions.isoName == session->get_source()->get_NAME()) &&
220 (formerSessions.parameterGroupNumber == session->get_parameter_group_number()))
222 formerSessions.sequenceNumber = session->sequenceNumber;
223 formerSessionMatched =
true;
228 if (!formerSessionMatched)
231 session->get_source()->get_NAME(),
232 session->get_parameter_group_number(),
233 session->sequenceNumber
242 if (
nullptr != session)
244 session->complete(successful);
257 std::uint8_t sequenceNumber = 0;
260 if ((formerSessions.isoName == name) && (formerSessions.parameterGroupNumber == parameterGroupNumber))
262 sequenceNumber = formerSessions.sequenceNumber + 1;
266 return sequenceNumber;
293 bool pgnNeedsParsing =
false;
297 ((
nullptr == callback.get_internal_control_function()) ||
300 pgnNeedsParsing =
true;
305 if (!pgnNeedsParsing)
316 if (
nullptr != session)
319 if (0 == actualFrameCount)
322 LOG_ERROR(
"[FP]: Existing session matched new frame counter, aborting the matching session.");
332 if (session->numberOfBytesTransferred < session->get_message_length())
335 session->add_number_of_bytes_transferred(1);
344 if (session->numberOfBytesTransferred >= session->get_message_length())
358 ((
nullptr == callback.get_internal_control_function()) ||
361 callback.get_callback()(completedMessage, callback.get_parent());
371 if (0 != actualFrameCount)
375 LOG_WARNING(
"[FP]: Ignoring FP message with PGN %u, no context available. The message may be processed when packet count returns to zero.",
384 LOG_WARNING(
"[FP]: Ignoring possible new FP session with advertised length > 233.");
389 LOG_WARNING(
"[FP]: Ignoring possible new FP session with advertised length <= 8.");
411 session->add_number_of_bytes_transferred(1);
422 if (
nullptr == session)
432 LOG_ERROR(
"[FP]: Rx session timed out.");
438 std::array<std::uint8_t, CAN_DATA_LENGTH> buffer;
440 for (std::uint8_t i = 0; i < session->get_number_of_remaining_packets(); i++)
442 buffer[0] = session->get_last_packet_number();
445 std::uint8_t startIndex = 1;
447 if (0 == session->get_total_bytes_transferred())
450 buffer[1] = session->get_message_length();
455 for (std::uint8_t j = 0; j < bytesThisFrame; j++)
457 std::uint8_t index =
static_cast<std::uint8_t
>(session->get_total_bytes_transferred()) + j;
458 if (index < session->get_message_length())
460 buffer[startIndex + j] = session->get_data().get_byte(index);
464 buffer[startIndex + j] = 0xFF;
470 std::static_pointer_cast<InternalControlFunction>(session->get_source()),
471 session->get_destination(),
474 session->add_number_of_bytes_transferred(bytesThisFrame);
480 LOG_ERROR(
"[FP]: Tx session timed out.");
487 if (session->get_number_of_remaining_packets() == 0)
498 return session->matches(source, destination) && (session->get_parameter_group_number() == parameterGroupNumber);
503 std::shared_ptr<ControlFunction> source,
504 std::shared_ptr<ControlFunction> destination)
507 auto result = std::find_if(
activeSessions.begin(),
activeSessions.end(), [&](
const std::shared_ptr<FastPacketProtocolSession> &session) {
508 return session->matches(source, destination) && (session->get_parameter_group_number() == parameterGroupNumber);
General constants used throughout this library.
The main class that manages the ISOBUS stack including: callbacks, Name to Address management,...
A class that acts as a logging sink. The intent is that someone could make their own derived class of...
CANPriority
Defines all the CAN frame priorities that can be encoded in a frame ID.
CANPriority get_priority() const
Returns the priority of the frame encoded in the identifier.
std::uint32_t get_parameter_group_number() const
Returns the PGN encoded in the identifier.
A class that represents data of a CAN message by using a callback function.
A class that represents data of a CAN message by holding a vector of bytes.
void set_byte(std::size_t index, std::uint8_t value)
Set the byte at the given index.
A class that represents a generic CAN message of arbitrary length.
@ Receive
Message is being received.
std::uint8_t get_can_port_index() const
Returns the CAN channel index associated with the message.
std::uint32_t get_data_length() const
Returns the length of the data in the CAN message.
std::shared_ptr< ControlFunction > get_source_control_function() const
Gets the source control function that the message is from.
std::uint8_t get_uint8_at(const std::uint32_t index) const
Get a 8-bit unsigned byte from the buffer at a specific index. A 8-bit unsigned byte can hold a value...
CANIdentifier get_identifier() const
Returns the identifier of the message.
std::shared_ptr< ControlFunction > get_destination_control_function() const
Gets the destination control function that the message is to.
bool is_broadcast() const
Returns whether the message is sent as a broadcast message / to all devices on the bus.
bool is_destination_our_device() const
Returns whether the message is destined for our device on the bus.
std::uint8_t get_message_length() const
Get the total number of bytes that will be sent or received in this session.
std::uint8_t get_total_number_of_packets() const
Get the total number of packets that will be sent or received in this session.
bool is_broadcast() const
Get whether or not this session is a broadcast session (BAM)
void add_number_of_bytes_transferred(std::uint8_t bytes)
Add number of bytes to the total number of bytes that have been sent or received in this session.
FastPacketProtocolSession(TransportProtocolSessionBase::Direction direction, std::unique_ptr< CANMessageData > data, std::uint32_t parameterGroupNumber, std::uint16_t totalMessageSize, std::uint8_t sequenceNumber, CANIdentifier::CANPriority priority, std::shared_ptr< ControlFunction > source, std::shared_ptr< ControlFunction > destination, TransmitCompleteCallback sessionCompleteCallback, void *parentPointer)
The constructor for a session, for advanced use only. In most cases, you should use the CANNetworkMan...
std::uint8_t get_number_of_remaining_packets() const
Get the number of packets that remain to be sent or received in this session.
std::uint32_t get_total_bytes_transferred() const override
Get the number of bytes that have been sent or received in this session.
std::uint8_t get_last_packet_number() const
Get the last packet number that was sent or received in this session.
static constexpr std::uint32_t FP_MIN_PARAMETER_GROUP_NUMBER
Start of PGNs that can be received via Fast Packet.
void add_session_history(const std::shared_ptr< FastPacketProtocolSession > &session)
Adds a session's info to the history so that we can continue the sequence number later.
bool allowAnyControlFunction
Denotes if messages for non-internal control functions should be parsed by this protocol.
static constexpr std::uint8_t FRAME_COUNTER_BIT_MASK
Bit mask for masking out the frame counter.
std::vector< std::shared_ptr< FastPacketProtocolSession > > activeSessions
A list of all active TP sessions.
static constexpr std::uint8_t SEQUENCE_NUMBER_BIT_MASK
Bit mask for masking out the sequence number bits.
static std::uint8_t calculate_number_of_frames(std::uint8_t messageLength)
Calculates the number of frames needed for a message.
void close_session(std::shared_ptr< FastPacketProtocolSession > session, bool successful)
Gracefully closes a session to prepare for a new session.
std::uint8_t get_new_sequence_number(NAME name, std::uint32_t parameterGroupNumber) const
Get the sequence number to use for a new session based on the history of past sessions.
void remove_multipacket_message_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, std::shared_ptr< InternalControlFunction > internalControlFunction=nullptr)
const CANMessageFrameCallback sendCANFrameCallback
A callback for sending a CAN frame.
Mutex sessionMutex
A mutex to lock the sessions list in case someone starts a Tx while the stack is processing sessions.
static constexpr std::uint32_t FP_TIMEOUT_MS
Protocol timeout in milliseconds.
static constexpr std::uint8_t SEQUENCE_NUMBER_BIT_OFFSET
The bit offset into the first byte of data to get the seq number.
std::vector< ParameterGroupNumberCallbackData > parameterGroupNumberCallbacks
A list of all parameter group number callbacks that will be parsed as fast packet messages.
FastPacketProtocol(const CANMessageFrameCallback &sendCANFrameCallback)
The constructor for the FastPacketProtocol, for advanced use only. In most cases, you should use the ...
void allow_any_control_function(bool allow)
Set whether or not to allow messages for non-internal control functions to be parsed by this protocol...
std::vector< FastPacketHistory > sessionHistory
Used to keep track of sequence numbers for future sessions.
void update()
Updates all sessions managed by this protocol manager instance.
std::shared_ptr< FastPacketProtocolSession > get_session(std::uint32_t parameterGroupNumber, std::shared_ptr< ControlFunction > source, std::shared_ptr< ControlFunction > destination)
Gets a FP session from the passed in source and destination and PGN combination.
static constexpr std::uint8_t PROTOCOL_BYTES_PER_FRAME
The number of payload bytes per frame for all but the first message, which has 6.
static constexpr std::uint8_t MAX_PROTOCOL_MESSAGE_LENGTH
Max message length based on there being 5 bits of sequence data.
void process_message(const CANMessage &message)
A generic way for a protocol to process a received message.
void register_multipacket_message_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent, std::shared_ptr< InternalControlFunction > internalControlFunction=nullptr)
Add a callback to be called when a message is received by the Fast Packet protocol.
void update_session(const std::shared_ptr< FastPacketProtocolSession > &session)
Update a single session.
static constexpr std::uint32_t FP_MAX_PARAMETER_GROUP_NUMBER
End of PGNs that can be received via Fast Packet.
bool has_session(std::uint32_t parameterGroupNumber, std::shared_ptr< ControlFunction > source, std::shared_ptr< ControlFunction > destination)
Checks if a session by the passed in source and destination and PGN combination exists.
bool send_multipacket_message(std::uint32_t parameterGroupNumber, const std::uint8_t *data, std::uint8_t messageLength, std::shared_ptr< InternalControlFunction > source, std::shared_ptr< ControlFunction > destination, CANIdentifier::CANPriority priority=CANIdentifier::CANPriority::PriorityDefault6, TransmitCompleteCallback txCompleteCallback=nullptr, void *parentPointer=nullptr, DataChunkCallback frameChunkCallback=nullptr)
Used to send CAN messages using fast packet.
A class that represents an ISO11783 control function NAME from an address claim.
A storage class to hold data about callbacks for a specific PGN.
An object to keep track of session information internally.
std::uint32_t get_message_length() const
Get the total number of bytes that will be sent or received in this session.
Direction
Enumerates the possible session directions.
@ Receive
We are receiving a message.
@ Transmit
We are transmitting a message.
This namespace encompasses all of the ISO11783 stack's functionality to reduce global namespace pollu...
DataSpan< const std::uint8_t > CANDataSpan
A read-only span of data for a CAN message.
std::function< bool(std::uint32_t parameterGroupNumber, CANDataSpan data, std::shared_ptr< InternalControlFunction > sourceControlFunction, std::shared_ptr< ControlFunction > destinationControlFunction, CANIdentifier::CANPriority priority)> CANMessageFrameCallback
A callback for communicating CAN message frames.
void(*)(std::uint32_t parameterGroupNumber, std::uint32_t dataLength, std::shared_ptr< InternalControlFunction > sourceControlFunction, std::shared_ptr< ControlFunction > destinationControlFunction, bool successful, void *parentPointer) TransmitCompleteCallback
A callback for when a transmit is completed by the stack.
constexpr std::uint8_t CAN_DATA_LENGTH
The length of a classical CAN frame.
void(*)(const CANMessage &message, void *parentPointer) CANLibCallback
A callback for control functions to get CAN messages.
bool(*)(std::uint32_t callbackIndex, std::uint32_t bytesOffset, std::uint32_t numberOfBytesNeeded, std::uint8_t *chunkBuffer, void *parentPointer) DataChunkCallback
A callback to get chunks of data for transfer by a protocol.
A protocol that handles the NMEA 2000 (IEC 61162-3) fast packet protocol.
A structure for keeping track of past sessions so we can resume with the right session number.