Libsockcanpp
A complete C++ wrapper around socketcan.
Public Member Functions | Static Public Attributes | Protected Member Functions | Private Member Functions | Private Attributes
sockcanpp::CanDriver Class Reference

CanDriver class; handles communication via CAN. More...

#include <CanDriver.hpp>

Collaboration diagram for sockcanpp::CanDriver:
Collaboration graph
[legend]

Public Member Functions

 CanDriver (const string canInterface, const int32_t canProtocol, const CanId defaultSenderId=0)
 !< A separate CAN protocol, used by certain embedded device OEMs. More...
 
 CanDriver (const string canInterface, const int32_t canProtocol, const int32_t filterMask, const CanId defaultSenderId=0)
 !< Constructor More...
 
 CanDriver ()
 
virtual ~CanDriver ()
 
CanDriversetDefaultSenderId (const CanId id)
 !< Destructor More...
 
const CanId getDefaultSenderId () const
 !< Sets the default sender ID More...
 
const int32_t getFilterMask () const
 !< Gets the default sender ID More...
 
const int32_t getMessageQueueSize () const
 !< Gets the filter mask used by this instance More...
 
const int32_t getSocketFd () const
 !< Gets the amount of CAN messages found after last calling waitForMessages() More...
 
virtual bool waitForMessages (milliseconds timeout=milliseconds(3000))
 !< The socket file descriptor used by this instance. More...
 
virtual CanMessage readMessage ()
 !< Waits for CAN messages to appear More...
 
virtual int32_t sendMessage (const CanMessage message, bool forceExtended=false)
 !< Attempts to read a single message from the bus More...
 
virtual int32_t sendMessageQueue (queue< CanMessage > messages, milliseconds delay=milliseconds(20), bool forceExtended=false)
 !< Attempts to send a single CAN message More...
 
virtual queue< CanMessagereadQueuedMessages ()
 !< Attempts to send a queue of messages More...
 
virtual void setCanFilterMask (const int32_t mask)
 !< Attempts to read all queued messages from the bus More...
 

Static Public Attributes

static const int32_t CAN_MAX_DATA_LENGTH = 8
 
static const int32_t CAN_SOCK_RAW = CAN_RAW
 !< The maximum amount of bytes allowed in a single CAN frame More...
 
static const int32_t CAN_SOCK_SEVEN = 7
 !< The raw CAN protocol More...
 

Protected Member Functions

virtual void initialiseSocketCan ()
 !< Attempts to set a new CAN filter mask to the BIOS More...
 
virtual void uninitialiseSocketCan ()
 !< Initialises socketcan More...
 

Private Member Functions

virtual CanMessage readMessageLock (bool const lock=true)
 !< Uninitialises socketcan More...
 

Private Attributes

CanId _defaultSenderId
 !< readMessage deadlock guard More...
 
int32_t _canFilterMask
 !< The ID to send messages with if no other ID was set. More...
 
int32_t _canProtocol
 !< The bit mask used to filter CAN messages More...
 
int32_t _socketFd
 !< The protocol used when communicating via CAN More...
 
int32_t _queueSize
 !< The CAN socket file descriptor More...
 
mutex _lock
 !< Mutex for thread-safety. More...
 
mutex _lockSend
 
string _canInterface
 

Detailed Description

CanDriver class; handles communication via CAN.

This class provides the means of easily communicating with other devices via CAN in C++.

Remarks
This class may be inherited by other applications and modified to suit your needs.

Definition at line 62 of file CanDriver.hpp.

Constructor & Destructor Documentation

◆ CanDriver() [1/3]

sockcanpp::CanDriver::CanDriver ( const string  canInterface,
const int32_t  canProtocol,
const CanId  defaultSenderId = 0 
)

!< A separate CAN protocol, used by certain embedded device OEMs.

Definition at line 81 of file CanDriver.cpp.

81 :
82 CanDriver(canInterface, canProtocol, 0 /* match all */, defaultSenderId) {}

References CanDriver().

◆ CanDriver() [2/3]

sockcanpp::CanDriver::CanDriver ( const string  canInterface,
const int32_t  canProtocol,
const int32_t  filterMask,
const CanId  defaultSenderId = 0 
)

!< Constructor

Definition at line 84 of file CanDriver.cpp.

84 :
85 _defaultSenderId(defaultSenderId), _canProtocol(canProtocol), _canInterface(canInterface), _canFilterMask(filterMask), _socketFd(-1) {
87 }
CanId _defaultSenderId
!< readMessage deadlock guard
Definition: CanDriver.hpp:102
int32_t _canProtocol
!< The bit mask used to filter CAN messages
Definition: CanDriver.hpp:105
int32_t _socketFd
!< The protocol used when communicating via CAN
Definition: CanDriver.hpp:106
int32_t _canFilterMask
!< The ID to send messages with if no other ID was set.
Definition: CanDriver.hpp:104
virtual void initialiseSocketCan()
!< Attempts to set a new CAN filter mask to the BIOS
Definition: CanDriver.cpp:243

References _canFilterMask, _canInterface, _canProtocol, _defaultSenderId, _socketFd, sockcanpp::CanId::CanId(), and initialiseSocketCan().

Referenced by CanDriver().

◆ CanDriver() [3/3]

sockcanpp::CanDriver::CanDriver ( )
inline

Definition at line 71 of file CanDriver.hpp.

71{}

◆ ~CanDriver()

virtual sockcanpp::CanDriver::~CanDriver ( )
inlinevirtual

Definition at line 72 of file CanDriver.hpp.

virtual void uninitialiseSocketCan()
!< Initialises socketcan
Definition: CanDriver.cpp:284

References uninitialiseSocketCan().

Member Function Documentation

◆ getDefaultSenderId()

const CanId sockcanpp::CanDriver::getDefaultSenderId ( ) const
inline

!< Sets the default sender ID

Definition at line 77 of file CanDriver.hpp.

77{ return this->_defaultSenderId; }

References _defaultSenderId.

◆ getFilterMask()

const int32_t sockcanpp::CanDriver::getFilterMask ( ) const
inline

!< Gets the default sender ID

Definition at line 79 of file CanDriver.hpp.

79{ return this->_canFilterMask; }

References _canFilterMask.

◆ getMessageQueueSize()

const int32_t sockcanpp::CanDriver::getMessageQueueSize ( ) const
inline

!< Gets the filter mask used by this instance

Definition at line 80 of file CanDriver.hpp.

80{ return this->_queueSize; }
int32_t _queueSize
!< The CAN socket file descriptor
Definition: CanDriver.hpp:107

References _queueSize.

◆ getSocketFd()

const int32_t sockcanpp::CanDriver::getSocketFd ( ) const
inline

!< Gets the amount of CAN messages found after last calling waitForMessages()

Definition at line 81 of file CanDriver.hpp.

81{ return this->_socketFd; }

References _socketFd.

◆ initialiseSocketCan()

void sockcanpp::CanDriver::initialiseSocketCan ( )
protectedvirtual

!< Attempts to set a new CAN filter mask to the BIOS

Initialises the underlying CAN socket.

Definition at line 243 of file CanDriver.cpp.

243 {
244 // unique_lock<mutex> locky(_lock);
245
246 struct sockaddr_can address;
247 struct ifreq ifaceRequest;
248 int64_t fdOptions = 0;
249 int32_t tmpReturn;
250
251 memset(&address, 0, sizeof(sizeof(struct sockaddr_can)));
252 memset(&ifaceRequest, 0, sizeof(sizeof(struct ifreq)));
253
254 _socketFd = socket(PF_CAN, SOCK_RAW, _canProtocol);
255
256 if (_socketFd == -1) {
257 throw CanInitException(formatString("FAILED to initialise socketcan! Error: %d => %s", errno, strerror(errno)));
258 }
259
260 strcpy(ifaceRequest.ifr_name, _canInterface.c_str());
261
262 if ((tmpReturn = ioctl(_socketFd, SIOCGIFINDEX, &ifaceRequest)) == -1) {
263 throw CanInitException(formatString("FAILED to perform IO control operation on socket %s! Error: %d => %s", _canInterface.c_str(), errno,
264 strerror(errno)));
265 }
266
267 fdOptions = fcntl(_socketFd, F_GETFL);
268 fdOptions |= O_NONBLOCK;
269 tmpReturn = fcntl(_socketFd, F_SETFL, fdOptions);
270
271 address.can_family = AF_CAN;
272 address.can_ifindex = ifaceRequest.ifr_ifindex;
273
275
276 if ((tmpReturn = bind(_socketFd, (struct sockaddr*)&address, sizeof(address))) == -1) {
277 throw CanInitException(formatString("FAILED to bind to socket CAN! Error: %d => %s", errno, strerror(errno)));
278 }
279 }
virtual void setCanFilterMask(const int32_t mask)
!< Attempts to read all queued messages from the bus
Definition: CanDriver.cpp:217
string formatString(const string &format, Args... args)
Formats a std string object.
Definition: CanDriver.hpp:131

References _canFilterMask, _canInterface, _canProtocol, _socketFd, sockcanpp::exceptions::CanInitException::CanInitException(), sockcanpp::formatString(), and setCanFilterMask().

Referenced by CanDriver().

◆ readMessage()

CanMessage sockcanpp::CanDriver::readMessage ( )
virtual

!< Waits for CAN messages to appear

Attempts to read a message from the associated CAN bus.

Returns
CanMessage The message read from the bus.

Definition at line 121 of file CanDriver.cpp.

121 {
122 return readMessageLock();
123 }
virtual CanMessage readMessageLock(bool const lock=true)
!< Uninitialises socketcan
Definition: CanDriver.cpp:130

References readMessageLock().

◆ readMessageLock()

CanMessage sockcanpp::CanDriver::readMessageLock ( bool const  lock = true)
privatevirtual

!< Uninitialises socketcan

readMessage deadlock guard, attempts to read a message from the associated CAN bus.

Returns
CanMessage The message read from the bus.

Definition at line 130 of file CanDriver.cpp.

130 {
131 std::unique_ptr<std::unique_lock<std::mutex>> _lockLck{nullptr};
132 if (lock)
133 _lockLck = std::unique_ptr<std::unique_lock<std::mutex>>{new std::unique_lock<std::mutex>{_lock}};
134 if (0 > _socketFd)
135 throw InvalidSocketException("Invalid socket!", _socketFd);
136 int32_t readBytes{0};
137 can_frame canFrame;
138 memset(&canFrame, 0, sizeof(can_frame));
139 readBytes = read(_socketFd, &canFrame, sizeof(can_frame));
140 if (0 > readBytes)
141 throw CanException(formatString("FAILED to read from CAN! Error: %d => %s", errno, strerror(errno)), _socketFd);
142 return CanMessage{canFrame};
143 }
mutex _lock
!< Mutex for thread-safety.
Definition: CanDriver.hpp:110

References _lock, _socketFd, sockcanpp::exceptions::CanException::CanException(), sockcanpp::CanMessage::CanMessage(), sockcanpp::formatString(), and sockcanpp::exceptions::InvalidSocketException::InvalidSocketException().

Referenced by readMessage(), and readQueuedMessages().

◆ readQueuedMessages()

queue< CanMessage > sockcanpp::CanDriver::readQueuedMessages ( )
virtual

!< Attempts to send a queue of messages

Attempts to read all messages stored in the buffer for the associated CAN bus.

Returns
queue<CanMessage> A queue containing the messages read from the bus buffer.

Definition at line 202 of file CanDriver.cpp.

202 {
203 if (_socketFd < 0)
204 throw InvalidSocketException("Invalid socket!", _socketFd);
205 unique_lock<mutex> locky(_lock);
206 queue<CanMessage> messages;
207 for (int32_t i = _queueSize; 0 < i; --i)
208 messages.emplace(readMessageLock(false));
209 return messages;
210 }

References _lock, _queueSize, _socketFd, sockcanpp::exceptions::InvalidSocketException::InvalidSocketException(), and readMessageLock().

◆ sendMessage()

int32_t sockcanpp::CanDriver::sendMessage ( const CanMessage  message,
bool  forceExtended = false 
)
virtual

!< Attempts to read a single message from the bus

Attempts to send a CAN message on the associated bus.

Parameters
messageThe message to be sent.
forceExtendedWhether or not to force use of an extended ID.
Returns
int32_t The amount of bytes sent on the bus.

Definition at line 153 of file CanDriver.cpp.

153 {
154 if (_socketFd < 0) { throw InvalidSocketException("Invalid socket!", _socketFd); }
155
156 unique_lock<mutex> locky(_lockSend);
157
158 int32_t bytesWritten = 0;
159
160 if (message.getFrameData().size() > CAN_MAX_DATA_LENGTH) {
161 throw CanException(formatString("INVALID data length! Message must be smaller than %d bytes!", CAN_MAX_DATA_LENGTH), _socketFd);
162 }
163
164 auto canFrame = message.getRawFrame();
165
166 if (forceExtended || ((uint32_t)message.getCanId() > CAN_SFF_MASK)) { canFrame.can_id |= CAN_EFF_FLAG; }
167
168 bytesWritten = write(_socketFd, (const void*)&canFrame, sizeof(canFrame));
169
170 if (bytesWritten == -1) { throw CanException(formatString("FAILED to write data to socket! Error: %d => %s", errno, strerror(errno)), _socketFd); }
171
172 return bytesWritten;
173 }
static const int32_t CAN_MAX_DATA_LENGTH
Definition: CanDriver.hpp:64

References _lockSend, _socketFd, CAN_MAX_DATA_LENGTH, sockcanpp::exceptions::CanException::CanException(), sockcanpp::formatString(), sockcanpp::CanMessage::getCanId(), sockcanpp::CanMessage::getFrameData(), sockcanpp::CanMessage::getRawFrame(), and sockcanpp::exceptions::InvalidSocketException::InvalidSocketException().

Referenced by sendMessageQueue().

◆ sendMessageQueue()

int32_t sockcanpp::CanDriver::sendMessageQueue ( queue< CanMessage messages,
milliseconds  delay = milliseconds(20),
bool  forceExtended = false 
)
virtual

!< Attempts to send a single CAN message

Attempts to send a queue of messages on the associated CAN bus.

Parameters
messagesA queue containing the messages to be sent.
delayIf greater than 0, will delay the sending of the next message.
forceExtendedWhether or not to force use of an extended ID.
Returns
int32_t The total amount of bytes sent.

Definition at line 184 of file CanDriver.cpp.

184 {
185 if (_socketFd < 0) { throw InvalidSocketException("Invalid socket!", _socketFd); }
186
187 int32_t totalBytesWritten = 0;
188
189 while (!messages.empty()) {
190 totalBytesWritten += sendMessage(messages.front(), forceExtended);
191 messages.pop();
192 }
193
194 return totalBytesWritten;
195 }
virtual int32_t sendMessage(const CanMessage message, bool forceExtended=false)
!< Attempts to read a single message from the bus
Definition: CanDriver.cpp:153

References _socketFd, sockcanpp::exceptions::InvalidSocketException::InvalidSocketException(), and sendMessage().

◆ setCanFilterMask()

void sockcanpp::CanDriver::setCanFilterMask ( const int32_t  mask)
virtual

!< Attempts to read all queued messages from the bus

Attempts to set the filter mask for the associated CAN bus.

Parameters
maskThe bit mask to apply.

Definition at line 217 of file CanDriver.cpp.

217 {
218 if (_socketFd < 0) { throw InvalidSocketException("Invalid socket!", _socketFd); }
219
220 unique_lock<mutex> locky(_lock);
221 can_filter canFilter;
222
223 canFilter.can_id = _defaultSenderId;
224 canFilter.can_mask = mask;
225
226 if (setsockopt(_socketFd, SOL_CAN_RAW, CAN_RAW_FILTER, &canFilter, sizeof(canFilter)) == -1) {
227 throw CanInitException(formatString("FAILED to set CAN filter mask %x on socket %d! Error: %d => %s", mask, _socketFd, errno, strerror(errno)));
228 }
229
230 _canFilterMask = mask;
231 }

References _canFilterMask, _defaultSenderId, _lock, _socketFd, sockcanpp::exceptions::CanInitException::CanInitException(), sockcanpp::formatString(), and sockcanpp::exceptions::InvalidSocketException::InvalidSocketException().

Referenced by initialiseSocketCan().

◆ setDefaultSenderId()

CanDriver & sockcanpp::CanDriver::setDefaultSenderId ( const CanId  id)
inline

!< Destructor

Definition at line 75 of file CanDriver.hpp.

75{ this->_defaultSenderId = id; return *this; }

References _defaultSenderId.

◆ uninitialiseSocketCan()

void sockcanpp::CanDriver::uninitialiseSocketCan ( )
protectedvirtual

!< Initialises socketcan

Closes the underlying CAN socket.

Definition at line 284 of file CanDriver.cpp.

284 {
285 unique_lock<mutex> locky(_lock);
286
287 if (_socketFd <= 0) { throw CanCloseException("Cannot close invalid socket!"); }
288
289 if (close(_socketFd) == -1) { throw CanCloseException(formatString("FAILED to close CAN socket! Error: %d => %s", errno, strerror(errno))); }
290
291 _socketFd = -1;
292 }

References _lock, _socketFd, sockcanpp::exceptions::CanCloseException::CanCloseException(), and sockcanpp::formatString().

Referenced by ~CanDriver().

◆ waitForMessages()

bool sockcanpp::CanDriver::waitForMessages ( milliseconds  timeout = milliseconds(3000))
virtual

!< The socket file descriptor used by this instance.

Blocks until one or more CAN messages appear on the bus, or until the timeout runs out.

Parameters
timeoutThe time (in millis) to wait before timing out.
Returns
true If messages are available on the bus.
false Otherwise.

Definition at line 99 of file CanDriver.cpp.

99 {
100 if (_socketFd < 0) { throw InvalidSocketException("Invalid socket!", _socketFd); }
101
102 unique_lock<mutex> locky(_lock);
103
104 fd_set readFileDescriptors;
105 timeval waitTime;
106 waitTime.tv_sec = timeout.count() / 1000;
107 waitTime.tv_usec = timeout.count() * 1000;
108
109 FD_ZERO(&readFileDescriptors);
110 FD_SET(_socketFd, &readFileDescriptors);
111 _queueSize = select(_socketFd + 1, &readFileDescriptors, 0, 0, &waitTime);
112
113 return _queueSize > 0;
114 }

References _lock, _queueSize, _socketFd, and sockcanpp::exceptions::InvalidSocketException::InvalidSocketException().

Field Documentation

◆ _canFilterMask

int32_t sockcanpp::CanDriver::_canFilterMask
private

!< The ID to send messages with if no other ID was set.

Definition at line 104 of file CanDriver.hpp.

Referenced by CanDriver(), getFilterMask(), initialiseSocketCan(), and setCanFilterMask().

◆ _canInterface

string sockcanpp::CanDriver::_canInterface
private

Definition at line 113 of file CanDriver.hpp.

Referenced by CanDriver(), and initialiseSocketCan().

◆ _canProtocol

int32_t sockcanpp::CanDriver::_canProtocol
private

!< The bit mask used to filter CAN messages

Definition at line 105 of file CanDriver.hpp.

Referenced by CanDriver(), and initialiseSocketCan().

◆ _defaultSenderId

CanId sockcanpp::CanDriver::_defaultSenderId
private

!< readMessage deadlock guard

Definition at line 102 of file CanDriver.hpp.

Referenced by CanDriver(), getDefaultSenderId(), setCanFilterMask(), and setDefaultSenderId().

◆ _lock

mutex sockcanpp::CanDriver::_lock
private

!< Mutex for thread-safety.

Definition at line 110 of file CanDriver.hpp.

Referenced by readMessageLock(), readQueuedMessages(), setCanFilterMask(), uninitialiseSocketCan(), and waitForMessages().

◆ _lockSend

mutex sockcanpp::CanDriver::_lockSend
private

Definition at line 111 of file CanDriver.hpp.

Referenced by sendMessage().

◆ _queueSize

int32_t sockcanpp::CanDriver::_queueSize
private

!< The CAN socket file descriptor

Definition at line 107 of file CanDriver.hpp.

Referenced by getMessageQueueSize(), readQueuedMessages(), and waitForMessages().

◆ _socketFd

int32_t sockcanpp::CanDriver::_socketFd
private

◆ CAN_MAX_DATA_LENGTH

const int32_t sockcanpp::CanDriver::CAN_MAX_DATA_LENGTH = 8
static

Definition at line 64 of file CanDriver.hpp.

Referenced by sendMessage().

◆ CAN_SOCK_RAW

const int32_t sockcanpp::CanDriver::CAN_SOCK_RAW = CAN_RAW
static

!< The maximum amount of bytes allowed in a single CAN frame

Definition at line 65 of file CanDriver.hpp.

◆ CAN_SOCK_SEVEN

const int32_t sockcanpp::CanDriver::CAN_SOCK_SEVEN = 7
static

!< The raw CAN protocol

Definition at line 66 of file CanDriver.hpp.


The documentation for this class was generated from the following files: