Skip to content
Open
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
15 changes: 13 additions & 2 deletions isobus/include/isobus/isobus/can_message.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,15 @@ namespace isobus
/// @param[in] source The source control function of the message
/// @param[in] destination The destination control function of the message
/// @param[in] CANPort The CAN channel index associated with the message
/// @param[in] timestamp_us The microsecond timestamp of the originating CAN frame, or 0 if unknown
CANMessage(Type type,
CANIdentifier identifier,
const std::uint8_t *dataBuffer,
std::uint32_t length,
std::shared_ptr<ControlFunction> source,
std::shared_ptr<ControlFunction> destination,
std::uint8_t CANPort);
std::uint8_t CANPort,
std::uint64_t timestamp_us = 0);

/// @brief Construct a CAN message from the parameters supplied
/// @param[in] type The type of the CAN message
Expand All @@ -75,12 +77,14 @@ namespace isobus
/// @param[in] source The source control function of the message
/// @param[in] destination The destination control function of the message
/// @param[in] CANPort The CAN channel index associated with the message
/// @param[in] timestamp_us The microsecond timestamp of the originating CAN frame, or 0 if unknown
CANMessage(Type type,
CANIdentifier identifier,
std::vector<std::uint8_t> data,
std::shared_ptr<ControlFunction> source,
std::shared_ptr<ControlFunction> destination,
std::uint8_t CANPort);
std::uint8_t CANPort,
std::uint64_t timestamp_us = 0);

/// @brief Returns the CAN message type
/// @returns The type of the CAN message
Expand Down Expand Up @@ -141,6 +145,12 @@ namespace isobus
/// @returns The CAN channel index associated with the message
std::uint8_t get_can_port_index() const;

/// @brief Returns the microsecond timestamp of the message.
/// @details For single-frame messages, this is the timestamp of the originating CAN frame.
/// For multi-frame messages, this is the timestamp of the last data-transfer frame.
/// @returns The microsecond timestamp of the message, or 0 if unset.
std::uint64_t get_timestamp_us() const;

/// @brief Sets the message data to the value supplied. Creates a copy.
/// @param[in] dataBuffer The data payload
/// @param[in] length the length of the data payload in bytes
Expand Down Expand Up @@ -262,6 +272,7 @@ namespace isobus
std::shared_ptr<ControlFunction> source; ///< The source control function of the message
std::shared_ptr<ControlFunction> destination; ///< The destination control function of the message
std::uint8_t CANPortIndex; ///< The CAN channel index associated with the message
std::uint64_t timestamp_us; ///< The microsecond timestamp of the originating frame
};

} // namespace isobus
Expand Down
3 changes: 2 additions & 1 deletion isobus/src/can_extended_transport_protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,8 @@ namespace isobus
std::move(data),
source,
destination,
0);
0,
message.get_timestamp_us());

canMessageReceivedCallback(completedMessage);
close_session(session, true);
Expand Down
17 changes: 13 additions & 4 deletions isobus/src/can_message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ namespace isobus
std::uint32_t length,
std::shared_ptr<ControlFunction> source,
std::shared_ptr<ControlFunction> destination,
std::uint8_t CANPort) :
std::uint8_t CANPort,
std::uint64_t timestamp_us) :
messageType(type),
identifier(identifier),
data(dataBuffer, dataBuffer + length),
source(source),
destination(destination),
CANPortIndex(CANPort)
CANPortIndex(CANPort),
timestamp_us(timestamp_us)
{
}

Expand All @@ -35,13 +37,15 @@ namespace isobus
std::vector<std::uint8_t> data,
std::shared_ptr<ControlFunction> source,
std::shared_ptr<ControlFunction> destination,
std::uint8_t CANPort) :
std::uint8_t CANPort,
std::uint64_t timestamp_us) :
messageType(type),
identifier(identifier),
data(std::move(data)),
source(source),
destination(destination),
CANPortIndex(CANPort)
CANPortIndex(CANPort),
timestamp_us(timestamp_us)
{
}

Expand Down Expand Up @@ -115,6 +119,11 @@ namespace isobus
return CANPortIndex;
}

std::uint64_t CANMessage::get_timestamp_us() const
{
return timestamp_us;
}

void CANMessage::set_data(const std::uint8_t *dataBuffer, std::uint32_t length)
{
assert(length <= ABSOLUTE_MAX_MESSAGE_LENGTH && "CANMessage::set_data() called with length greater than maximum supported");
Expand Down
9 changes: 6 additions & 3 deletions isobus/src/can_network_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,8 @@ namespace isobus
rxFrame.dataLength,
get_control_function(rxFrame.channel, identifier.get_source_address()),
get_control_function(rxFrame.channel, identifier.get_destination_address()),
rxFrame.channel);
rxFrame.channel,
rxFrame.timestamp_us);

update_busload(rxFrame.channel, rxFrame.get_number_bits_in_message());

Expand All @@ -317,7 +318,8 @@ namespace isobus
txFrame.dataLength,
get_control_function(txFrame.channel, identifier.get_source_address()),
get_control_function(txFrame.channel, identifier.get_destination_address()),
txFrame.channel);
txFrame.channel,
txFrame.timestamp_us);

if (initialized)
{
Expand Down Expand Up @@ -536,7 +538,8 @@ namespace isobus
message.get_data(),
message.get_source_control_function(),
message.get_destination_control_function(),
i);
i,
message.get_timestamp_us());
this->protocol_message_callback(message);
};
transportProtocols.at(i).reset(new TransportProtocolManager(send_frame_callback, receive_message_callback, &configuration));
Expand Down
3 changes: 2 additions & 1 deletion isobus/src/can_transport_protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,8 @@ namespace isobus
std::move(data),
source,
destination,
0);
0,
message.get_timestamp_us());

canMessageReceivedCallback(completedMessage);
close_session(session, true);
Expand Down
3 changes: 2 additions & 1 deletion isobus/src/nmea2000_fast_packet_protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,8 @@ namespace isobus
std::move(data),
message.get_source_control_function(),
message.get_destination_control_function(),
message.get_can_port_index());
message.get_can_port_index(),
message.get_timestamp_us());

// Find the appropriate callback and let them know
for (const auto &callback : parameterGroupNumberCallbacks)
Expand Down
70 changes: 70 additions & 0 deletions test/can_message_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ using namespace isobus;
std::uint64_t value64;
std::uint16_t value16;

constexpr std::uint64_t EXPECTED_TIMESTAMP = 1000000;

void callback(const CANMessage &message, void *)
{
EXPECT_EQ(EXPECTED_TIMESTAMP, message.get_timestamp_us());
value16 = message.get_int16_at(0);
EXPECT_EQ(value16, 513);
value16 = message.get_int16_at(0, CANMessage::ByteFormat::BigEndian);
Expand Down Expand Up @@ -66,8 +69,75 @@ TEST(CAN_MESSAGE_TESTS, DataCorrectnessTest)
CANNetworkManager::CANNetwork.process_receive_can_message_frame(testFrame);
CANNetworkManager::CANNetwork.update();
testFrame.identifier = 0x18E1FFAA;
testFrame.timestamp_us = EXPECTED_TIMESTAMP;
CANNetworkManager::CANNetwork.process_receive_can_message_frame(testFrame);
CANNetworkManager::CANNetwork.update();
CANNetworkManager::CANNetwork.remove_global_parameter_group_number_callback(0xE100, callback, nullptr);
CANHardwareInterface::stop();
}

TEST(CAN_MESSAGE_TESTS, DefaultTimestampIsZero)
{
{
const std::uint8_t data[] = { 0x01, 0x02 };

CANMessage message{
CANMessage::Type::Receive,
CANIdentifier{ 0x18E1FFAA },
data,
sizeof(data),
nullptr,
nullptr,
0,
};

EXPECT_EQ(0, message.get_timestamp_us());
}

{
const CANMessage message{
CANMessage::Type::Receive,
CANIdentifier{ 0x18E1FFAA },
std::vector<std::uint8_t>{ 0x01, 0x02 },
nullptr,
nullptr,
0,
};

EXPECT_EQ(0, message.get_timestamp_us());
}
}

TEST(CAN_MESSAGE_TESTS, ExplicitTimestampIsPreserved)
{
{
const std::uint8_t data[] = { 0x01, 0x02 };

CANMessage message{
CANMessage::Type::Receive,
CANIdentifier{ 0x18E1FFAA },
data,
sizeof(data),
nullptr,
nullptr,
0,
EXPECTED_TIMESTAMP,
};

EXPECT_EQ(EXPECTED_TIMESTAMP, message.get_timestamp_us());
}

{
CANMessage message{
CANMessage::Type::Receive,
CANIdentifier{ 0x18FEFFFE },
std::vector<std::uint8_t>{ 0x01, 0x02 },
nullptr,
nullptr,
0,
EXPECTED_TIMESTAMP,
};

EXPECT_EQ(EXPECTED_TIMESTAMP, message.get_timestamp_us());
}
}
20 changes: 12 additions & 8 deletions test/helpers/messaging_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,18 @@ namespace test_helpers
return identifier;
}

isobus::CANMessage create_message(std::uint8_t priority, std::uint32_t parameterGroupNumber, std::shared_ptr<isobus::ControlFunction> destination, std::shared_ptr<isobus::ControlFunction> source, std::initializer_list<std::uint8_t> data)
isobus::CANMessage create_message(std::uint8_t priority, std::uint32_t parameterGroupNumber, std::shared_ptr<isobus::ControlFunction> destination, std::shared_ptr<isobus::ControlFunction> source, std::initializer_list<std::uint8_t> data, std::uint64_t timestamp_us)
{
return create_message(priority, parameterGroupNumber, destination, source, data.begin(), data.size());
return create_message(priority, parameterGroupNumber, destination, source, data.begin(), data.size(), timestamp_us);
}

CANMessage create_message(std::uint8_t priority,
std::uint32_t parameterGroupNumber,
std::shared_ptr<ControlFunction> destination,
std::shared_ptr<ControlFunction> source,
const std::uint8_t *dataBuffer,
std::uint32_t dataLength)
std::uint32_t dataLength,
std::uint64_t timestamp_us)
{
EXPECT_NE(source, nullptr);
EXPECT_TRUE(source->get_address_valid());
Expand All @@ -86,20 +87,22 @@ namespace test_helpers
dataLength,
source,
destination,
0); //! TODO: hack for now, will be fixed when we remove CANNetwork Singleton
0, //! TODO: hack for now, will be fixed when we remove CANNetwork Singleton
timestamp_us);
return message;
}

isobus::CANMessage create_message_broadcast(std::uint8_t priority, std::uint32_t parameterGroupNumber, std::shared_ptr<isobus::ControlFunction> source, std::initializer_list<std::uint8_t> data)
isobus::CANMessage create_message_broadcast(std::uint8_t priority, std::uint32_t parameterGroupNumber, std::shared_ptr<isobus::ControlFunction> source, std::initializer_list<std::uint8_t> data, std::uint64_t timestamp_us)
{
return create_message_broadcast(priority, parameterGroupNumber, source, data.begin(), data.size());
return create_message_broadcast(priority, parameterGroupNumber, source, data.begin(), data.size(), timestamp_us);
}

CANMessage create_message_broadcast(std::uint8_t priority,
std::uint32_t parameterGroupNumber,
std::shared_ptr<ControlFunction> source,
const std::uint8_t *dataBuffer,
std::uint32_t dataLength)
std::uint32_t dataLength,
std::uint64_t timestamp_us)
{
EXPECT_NE(source, nullptr);
EXPECT_TRUE(source->get_address_valid());
Expand All @@ -111,7 +114,8 @@ namespace test_helpers
dataLength,
source,
nullptr,
0); //! TODO: hack for now, will be fixed when we remove CANNetwork Singleton
0, //! TODO: hack for now, will be fixed when we remove CANNetwork Singleton
timestamp_us);
return message;
}

Expand Down
12 changes: 8 additions & 4 deletions test/helpers/messaging_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,29 @@ namespace test_helpers
std::uint32_t parameterGroupNumber,
std::shared_ptr<isobus::ControlFunction> destination,
std::shared_ptr<isobus::ControlFunction> source,
std::initializer_list<std::uint8_t> data);
std::initializer_list<std::uint8_t> data,
std::uint64_t timestamp_us = 0);

isobus::CANMessage create_message(std::uint8_t priority,
std::uint32_t parameterGroupNumber,
std::shared_ptr<isobus::ControlFunction> destination,
std::shared_ptr<isobus::ControlFunction> source,
const std::uint8_t *dataBuffer,
std::uint32_t dataLength);
std::uint32_t dataLength,
std::uint64_t timestamp_us = 0);

isobus::CANMessage create_message_broadcast(std::uint8_t priority,
std::uint32_t parameterGroupNumber,
std::shared_ptr<isobus::ControlFunction> source,
std::initializer_list<std::uint8_t> data);
std::initializer_list<std::uint8_t> data,
std::uint64_t timestamp_us = 0);

isobus::CANMessage create_message_broadcast(std::uint8_t priority,
std::uint32_t parameterGroupNumber,
std::shared_ptr<isobus::ControlFunction> source,
const std::uint8_t *dataBuffer,
std::uint32_t dataLength);
std::uint32_t dataLength,
std::uint64_t timestamp_us = 0);

isobus::CANMessageFrame create_message_frame_raw(std::uint32_t identifier,
std::initializer_list<std::uint8_t> data);
Expand Down
5 changes: 4 additions & 1 deletion test/transport_protocol_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ TEST_F(TransportProtocolTest, BroadcastMessageReceiving)
{
constexpr std::uint32_t pgnToReceive = 0xFEEC;
constexpr std::array<std::uint8_t, 17> dataToReceive = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11 };
constexpr std::uint64_t lastDTTimestamp = 1000000;

auto originator = test_helpers::create_mock_control_function(0x01);

Expand All @@ -40,6 +41,7 @@ TEST_F(TransportProtocolTest, BroadcastMessageReceiving)
{
EXPECT_EQ(message.get_data()[i], dataToReceive[i]);
}
EXPECT_EQ(lastDTTimestamp, message.get_timestamp_us());
messageCount++;
};

Expand Down Expand Up @@ -111,7 +113,8 @@ TEST_F(TransportProtocolTest, BroadcastMessageReceiving)
0xFF,
0xFF,
0xFF,
}));
},
lastDTTimestamp));

// We now expect the message to be received
ASSERT_EQ(messageCount, 1);
Expand Down
Loading