19 const std::uint8_t *dataBuffer,
21 std::shared_ptr<ControlFunction> source,
22 std::shared_ptr<ControlFunction> destination,
23 std::uint8_t CANPort) :
25 identifier(identifier),
26 data(dataBuffer, dataBuffer + length),
28 destination(destination),
35 std::vector<std::uint8_t> data,
36 std::shared_ptr<ControlFunction> source,
37 std::shared_ptr<ControlFunction> destination,
38 std::uint8_t CANPort) :
40 identifier(identifier),
41 data(std::move(data)),
43 destination(destination),
75 return (
nullptr !=
source) &&
source->get_address_valid();
126 assert(
nullptr != dataBuffer &&
"CANMessage::set_data() called with nullptr dataBuffer");
128 data.insert(
data.end(), dataBuffer, dataBuffer + length);
133 assert(insertPosition <=
ABSOLUTE_MAX_MESSAGE_LENGTH &&
"CANMessage::set_data() called with insertPosition greater than maximum supported");
135 data[insertPosition] = dataByte;
150 return data.at(index);
155 return static_cast<std::int8_t
>(
data.at(index));
160 std::uint16_t retVal;
161 if (ByteFormat::LittleEndian == format)
163 retVal =
data.at(index);
164 retVal |=
static_cast<std::uint16_t
>(
data.at(index + 1)) << 8;
168 retVal =
static_cast<std::uint16_t
>(
data.at(index)) << 8;
169 retVal |=
data.at(index + 1);
177 if (ByteFormat::LittleEndian == format)
179 retVal =
static_cast<std::int16_t
>(
data.at(index));
180 retVal |=
static_cast<std::int16_t
>(
data.at(index + 1)) << 8;
184 retVal =
static_cast<std::int16_t
>(
data.at(index)) << 8;
185 retVal |=
static_cast<std::int16_t
>(
data.at(index + 1));
192 std::uint32_t retVal;
193 if (ByteFormat::LittleEndian == format)
195 retVal =
data.at(index);
196 retVal |=
static_cast<std::uint32_t
>(
data.at(index + 1)) << 8;
197 retVal |=
static_cast<std::uint32_t
>(
data.at(index + 2)) << 16;
201 retVal =
static_cast<std::uint32_t
>(
data.at(index + 2)) << 16;
202 retVal |=
static_cast<std::uint32_t
>(
data.at(index + 1)) << 8;
203 retVal |=
data.at(index + 2);
211 if (ByteFormat::LittleEndian == format)
213 retVal =
static_cast<std::int32_t
>(
data.at(index));
214 retVal |=
static_cast<std::int32_t
>(
data.at(index + 1)) << 8;
215 retVal |=
static_cast<std::int32_t
>(
data.at(index + 2)) << 16;
219 retVal =
static_cast<std::int32_t
>(
data.at(index + 2)) << 16;
220 retVal |=
static_cast<std::int32_t
>(
data.at(index + 1)) << 8;
221 retVal |=
static_cast<std::int32_t
>(
data.at(index + 2));
228 std::uint32_t retVal;
229 if (ByteFormat::LittleEndian == format)
231 retVal =
data.at(index);
232 retVal |=
static_cast<std::uint32_t
>(
data.at(index + 1)) << 8;
233 retVal |=
static_cast<std::uint32_t
>(
data.at(index + 2)) << 16;
234 retVal |=
static_cast<std::uint32_t
>(
data.at(index + 3)) << 24;
238 retVal =
static_cast<std::uint32_t
>(
data.at(index)) << 24;
239 retVal |=
static_cast<std::uint32_t
>(
data.at(index + 1)) << 16;
240 retVal |=
static_cast<std::uint32_t
>(
data.at(index + 2)) << 8;
241 retVal |=
data.at(index + 3);
249 if (ByteFormat::LittleEndian == format)
251 retVal =
static_cast<std::int32_t
>(
data.at(index));
252 retVal |=
static_cast<std::int32_t
>(
data.at(index + 1)) << 8;
253 retVal |=
static_cast<std::int32_t
>(
data.at(index + 2)) << 16;
254 retVal |=
static_cast<std::int32_t
>(
data.at(index + 3)) << 24;
258 retVal =
static_cast<std::int32_t
>(
data.at(index)) << 24;
259 retVal |=
static_cast<std::int32_t
>(
data.at(index + 1)) << 16;
260 retVal |=
static_cast<std::int32_t
>(
data.at(index + 2)) << 8;
261 retVal |=
static_cast<std::int32_t
>(
data.at(index + 3));
268 std::uint64_t retVal;
269 if (ByteFormat::LittleEndian == format)
271 retVal =
data.at(index);
272 retVal |=
static_cast<std::uint64_t
>(
data.at(index + 1)) << 8;
273 retVal |=
static_cast<std::uint64_t
>(
data.at(index + 2)) << 16;
274 retVal |=
static_cast<std::uint64_t
>(
data.at(index + 3)) << 24;
275 retVal |=
static_cast<std::uint64_t
>(
data.at(index + 4)) << 32;
276 retVal |=
static_cast<std::uint64_t
>(
data.at(index + 5)) << 40;
277 retVal |=
static_cast<std::uint64_t
>(
data.at(index + 6)) << 48;
278 retVal |=
static_cast<std::uint64_t
>(
data.at(index + 7)) << 56;
282 retVal =
static_cast<std::uint64_t
>(
data.at(index)) << 56;
283 retVal |=
static_cast<std::uint64_t
>(
data.at(index + 1)) << 48;
284 retVal |=
static_cast<std::uint64_t
>(
data.at(index + 2)) << 40;
285 retVal |=
static_cast<std::uint64_t
>(
data.at(index + 3)) << 32;
286 retVal |=
static_cast<std::uint64_t
>(
data.at(index + 4)) << 24;
287 retVal |=
static_cast<std::uint64_t
>(
data.at(index + 5)) << 16;
288 retVal |=
static_cast<std::uint64_t
>(
data.at(index + 6)) << 8;
289 retVal |=
data.at(index + 7);
297 if (ByteFormat::LittleEndian == format)
299 retVal =
static_cast<std::int64_t
>(
data.at(index));
300 retVal |=
static_cast<std::int64_t
>(
data.at(index + 1)) << 8;
301 retVal |=
static_cast<std::int64_t
>(
data.at(index + 2)) << 16;
302 retVal |=
static_cast<std::int64_t
>(
data.at(index + 3)) << 24;
303 retVal |=
static_cast<std::int64_t
>(
data.at(index + 4)) << 32;
304 retVal |=
static_cast<std::int64_t
>(
data.at(index + 5)) << 40;
305 retVal |=
static_cast<std::int64_t
>(
data.at(index + 6)) << 48;
306 retVal |=
static_cast<std::int64_t
>(
data.at(index + 7)) << 56;
310 retVal =
static_cast<std::int64_t
>(
data.at(index)) << 56;
311 retVal |=
static_cast<std::int64_t
>(
data.at(index + 1)) << 48;
312 retVal |=
static_cast<std::int64_t
>(
data.at(index + 2)) << 40;
313 retVal |=
static_cast<std::int64_t
>(
data.at(index + 3)) << 32;
314 retVal |=
static_cast<std::int64_t
>(
data.at(index + 4)) << 24;
315 retVal |=
static_cast<std::int64_t
>(
data.at(index + 5)) << 16;
316 retVal |=
static_cast<std::int64_t
>(
data.at(index + 6)) << 8;
317 retVal |=
static_cast<std::int64_t
>(
data.at(index + 7));
324 assert(length <= 8 - bitIndex &&
"length must be less than or equal to 8 - bitIndex");
325 std::uint8_t mask = ((1 << length) - 1) << bitIndex;
326 return (get_uint8_at(byteIndex) & mask) == mask;
331 std::uint64_t retVal = 0;
332 std::uint8_t currentByte = 0;
333 std::uint32_t endBitIndex = startBitIndex + length - 1;
334 std::uint32_t bitCounter = 0;
335 std::uint32_t amountOfBytesLeft = (length + 8 - 1) / 8;
336 std::uint32_t startAmountOfBytes = amountOfBytesLeft;
337 std::uint8_t indexOfFinalByteBit = 7;
339 if (endBitIndex > 8 *
data.size() || length < 1 || startBitIndex >= 8 *
data.size())
341 LOG_ERROR(
"End bit index is greater than length or startBitIndex is wrong or startBitIndex is greater than endBitIndex");
345 for (
auto i = startBitIndex; i <= endBitIndex; i++)
347 auto byteIndex = i / 8;
348 auto bitIndexWithinByte = i % 8;
349 auto bit = (
data.at(byteIndex) >> (indexOfFinalByteBit - bitIndexWithinByte)) & 1;
350 if (length - bitCounter < 8)
352 currentByte |=
static_cast<uint8_t
>(bit) << (length - 1 - bitCounter);
356 currentByte |=
static_cast<uint8_t
>(bit) << (indexOfFinalByteBit - bitIndexWithinByte);
359 if ((bitCounter + 1) % 8 == 0 || i == endBitIndex)
361 if (ByteFormat::LittleEndian == format)
363 retVal |= (
static_cast<uint64_t
>(currentByte) << (startAmountOfBytes - amountOfBytesLeft) * 8);
367 retVal |= (
static_cast<uint64_t
>(currentByte) << ((amountOfBytesLeft * 8) - 8));
An abstraction of a CAN message, could be > 8 data bytes.
A class that acts as a logging sink. The intent is that someone could make their own derived class of...
A utility class that allows easy interpretation of a 32 bit CAN identifier.
static constexpr std::uint32_t UNDEFINED_PARAMETER_GROUP_NUMBER
A fake PGN used internally to denote a NULL PGN.
std::uint32_t get_parameter_group_number() const
Returns the PGN encoded in the identifier.
static constexpr std::uint8_t GLOBAL_ADDRESS
The broadcast CAN address.
A class that represents a generic CAN message of arbitrary length.
std::int16_t get_int16_at(const std::uint32_t index, const ByteFormat format=ByteFormat::LittleEndian) const
Get a 16-bit signed integer from the buffer at a specific index. A 16-bit signed integer can hold a v...
bool is_source(std::shared_ptr< ControlFunction > controlFunction) const
Returns whether the message is originated from the control function.
static const std::uint32_t ABSOLUTE_MAX_MESSAGE_LENGTH
ISO11783-3 defines this: The maximum number of packets that can be sent in a single connection with e...
std::shared_ptr< ControlFunction > source
The source control function of the message.
Type
The internal message type.
@ Receive
Message is being received.
bool is_destination(std::shared_ptr< ControlFunction > controlFunction) const
Returns whether the message is destined for the control function.
bool has_valid_destination_control_function() const
Returns whether the message is sent to a specific device on the bus.
std::int32_t get_int24_at(const std::uint32_t index, const ByteFormat format=ByteFormat::LittleEndian) const
Get a right-aligned 24-bit integer from the buffer (returned as a int32_t) at a specific index....
Type messageType
The internal message type associated with the message.
Type get_type() const
Returns the CAN message type.
static CANMessage create_invalid_message()
Factory method to construct an intentionally invalid CANMessage.
ByteFormat
The different byte formats that can be used when reading bytes from the buffer.
void set_data(const std::uint8_t *dataBuffer, std::uint32_t length)
Sets the message data to the value supplied. Creates a copy.
std::uint8_t get_can_port_index() const
Returns the CAN channel index associated with the message.
const std::vector< std::uint8_t > & get_data() const
Gets a reference to the data in the CAN message.
std::uint32_t get_data_length() const
Returns the length of the data in the CAN message.
bool has_valid_source_control_function() const
Returns whether the message is sent by a device that claimed its address on the bus.
void set_data_size(std::uint32_t length)
Sets the size of the data payload.
std::uint32_t get_uint24_at(const std::uint32_t index, const ByteFormat format=ByteFormat::LittleEndian) const
Get a right-aligned 24-bit integer from the buffer (returned as a uint32_t) at a specific index....
std::uint64_t get_data_custom_length(const std::uint32_t startBitIndex, const std::uint32_t length, const ByteFormat format=ByteFormat::LittleEndian) const
Get a 64-bit unsinged integer from the buffer at a specific index but custom length Why 64 bit?...
CANIdentifier identifier
The CAN ID of the 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...
std::shared_ptr< ControlFunction > destination
The destination control function of the message.
bool is_parameter_group_number(CANLibParameterGroupNumber parameterGroupNumber) const
Compares the identifier of the message to the parameter group number (PGN) supplied.
std::vector< std::uint8_t > data
A data buffer for the message, used when not using data chunk callbacks.
void set_identifier(const CANIdentifier &value)
Sets the CAN ID of the message.
std::int32_t get_int32_at(const std::uint32_t index, const ByteFormat format=ByteFormat::LittleEndian) const
Get a 32-bit signed integer from the buffer at a specific index. A 32-bit signed integer can hold a v...
std::int8_t get_int8_at(const std::uint32_t index) const
Get a 8-bit signed byte from the buffer at a specific index. A 8-bit signed byte can hold a value bet...
std::uint16_t get_uint16_at(const std::uint32_t index, const ByteFormat format=ByteFormat::LittleEndian) const
Get a 16-bit unsigned integer from the buffer at a specific index. A 16-bit unsigned integer can hold...
CANIdentifier get_identifier() const
Returns the identifier of the message.
std::int64_t get_int64_at(const std::uint32_t index, const ByteFormat format=ByteFormat::LittleEndian) const
Get a 64-bit signed integer from the buffer at a specific index. A 64-bit signed integer can hold a v...
std::uint8_t CANPortIndex
The CAN channel index associated with the message.
bool get_bool_at(const std::uint32_t byteIndex, const std::uint8_t bitIndex, const std::uint8_t length=1) const
Get a bit-boolean from the buffer at a specific index.
std::uint32_t get_uint32_at(const std::uint32_t index, const ByteFormat format=ByteFormat::LittleEndian) const
Get a 32-bit unsigned integer from the buffer at a specific index. A 32-bit unsigned integer can hold...
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)
Construct a CAN message from the parameters supplied.
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::uint64_t get_uint64_at(const std::uint32_t index, const ByteFormat format=ByteFormat::LittleEndian) const
Get a 64-bit unsigned integer from the buffer at a specific index. A 64-bit unsigned integer can hold...
@ Internal
The control function is part of our stack and can address claim.
This namespace encompasses all of the ISO11783 stack's functionality to reduce global namespace pollu...
CANLibParameterGroupNumber
PGNs commonly used by the CAN stack.