Libsockcanpp
A complete C++ wrapper around socketcan.
CanDriver.hpp
Go to the documentation of this file.
1/**
2 * @file CanDriver.hpp
3 * @author Simon Cahill (simonc@online.de)
4 * @brief Contains the declarations for the SocketCAN wrapper in C++.
5 * @version 0.1
6 * @date 2020-07-01
7 *
8 * @copyright Copyright (c) 2020
9 *
10 * Copyright 2020 Simon Cahill
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 */
24
25#ifndef LIBSOCKCANPP_INCLUDE_CANDRIVER_HPP
26#define LIBSOCKCANPP_INCLUDE_CANDRIVER_HPP
27
28//////////////////////////////
29// SYSTEM INCLUDES //
30//////////////////////////////
31#include <mutex>
32#include <queue>
33#include <string>
34#include <thread>
35
36//////////////////////////////
37// LOCAL INCLUDES //
38//////////////////////////////
39#include "CanId.hpp"
40#include "CanMessage.hpp"
41
42/**
43 * @brief Main library namespace.
44 *
45 * This namespace contains the library's main code.
46 */
47namespace sockcanpp {
48
49 using std::chrono::milliseconds;
50 using std::mutex;
51 using std::string;
52 using std::queue;
53
54 /**
55 * @brief CanDriver class; handles communication via CAN.
56 *
57 * This class provides the means of easily communicating with other devices via CAN in C++.
58 *
59 * @remarks
60 * This class may be inherited by other applications and modified to suit your needs.
61 */
62 class CanDriver {
63 public: // +++ Static +++
64 static const int32_t CAN_MAX_DATA_LENGTH; ///!< The maximum amount of bytes allowed in a single CAN frame
65 static const int32_t CAN_SOCK_RAW; ///!< The raw CAN protocol
66 static const int32_t CAN_SOCK_SEVEN; ///!< A separate CAN protocol, used by certain embedded device OEMs.
67
68 public: // +++ Constructor / Destructor +++
69 CanDriver(const string canInterface, const int32_t canProtocol, const CanId defaultSenderId = 0); ///!< Constructor
70 CanDriver(const string canInterface, const int32_t canProtocol, const int32_t filterMask, const CanId defaultSenderId = 0);
72 virtual ~CanDriver() { uninitialiseSocketCan(); } ///!< Destructor
73
74 public: // +++ Getter / Setter +++
75 CanDriver& setDefaultSenderId(const CanId id) { this->_defaultSenderId = id; return *this; } ///!< Sets the default sender ID
76
77 const CanId getDefaultSenderId() const { return this->_defaultSenderId; } ///!< Gets the default sender ID
78
79 const int32_t getFilterMask() const { return this->_canFilterMask; } ///!< Gets the filter mask used by this instance
80 const int32_t getMessageQueueSize() const { return this->_queueSize; } ///!< Gets the amount of CAN messages found after last calling waitForMessages()
81 const int32_t getSocketFd() const { return this->_socketFd; } ///!< The socket file descriptor used by this instance.
82
83 public: // +++ I/O +++
84 virtual bool waitForMessages(milliseconds timeout = milliseconds(3000)); ///!< Waits for CAN messages to appear
85
86 virtual CanMessage readMessage(); ///!< Attempts to read a single message from the bus
87
88 virtual int32_t sendMessage(const CanMessage message, bool forceExtended = false); ///!< Attempts to send a single CAN message
89 virtual int32_t sendMessageQueue(queue<CanMessage> messages,
90 milliseconds delay = milliseconds(20), bool forceExtended = false); ///!< Attempts to send a queue of messages
91
92 virtual queue<CanMessage> readQueuedMessages(); ///!< Attempts to read all queued messages from the bus
93
94 virtual void setCanFilterMask(const int32_t mask); ///!< Attempts to set a new CAN filter mask to the BIOS
95
96 protected: // +++ Socket Management +++
97 virtual void initialiseSocketCan(); ///!< Initialises socketcan
98 virtual void uninitialiseSocketCan(); ///!< Uninitialises socketcan
99
100 private:
101 virtual CanMessage readMessageLock(bool const lock = true); ///!< readMessage deadlock guard
102 CanId _defaultSenderId; ///!< The ID to send messages with if no other ID was set.
103
104 int32_t _canFilterMask; ///!< The bit mask used to filter CAN messages
105 int32_t _canProtocol; ///!< The protocol used when communicating via CAN
106 int32_t _socketFd; ///!< The CAN socket file descriptor
107 int32_t _queueSize; ////!< The size of the message queue read by waitForMessages()
108
109 ///!< Mutex for thread-safety.
112
113 string _canInterface; ///!< The CAN interface used for communication (e.g. can0, can1, ...)
114
115 };
116
117
118
119 /**
120 * @brief Formats a std string object.
121 *
122 * @remarks Yoinked from https://github.com/Beatsleigher/liblogpp :)
123 *
124 * @tparam Args The formatting argument types.
125 * @param format The format string.
126 * @param args The format arguments (strings must be converted to C-style strings!)
127 *
128 * @return string The formatted string.
129 */
130 template<typename... Args>
131 string formatString(const string& format, Args... args) {
132 using std::unique_ptr;
133 auto stringSize = snprintf(NULL, 0, format.c_str(), args...) + 1; // +1 for \0
134 unique_ptr<char[]> buffer(new char[stringSize]);
135
136 snprintf(buffer.get(), stringSize, format.c_str(), args...);
137
138 return string(buffer.get(), buffer.get() + stringSize - 1); // std::string handles termination for us.
139 }
140
141}
142
143#endif // LIBSOCKCANPP_INCLUDE_CANDRIVER_HPP
CanDriver class; handles communication via CAN.
Definition: CanDriver.hpp:62
CanDriver(const string canInterface, const int32_t canProtocol, const CanId defaultSenderId=0)
!< A separate CAN protocol, used by certain embedded device OEMs.
Definition: CanDriver.cpp:81
virtual CanMessage readMessage()
!< Waits for CAN messages to appear
Definition: CanDriver.cpp:121
const int32_t getFilterMask() const
!< Gets the default sender ID
Definition: CanDriver.hpp:79
static const int32_t CAN_SOCK_RAW
!< The maximum amount of bytes allowed in a single CAN frame
Definition: CanDriver.hpp:65
static const int32_t CAN_SOCK_SEVEN
!< The raw CAN protocol
Definition: CanDriver.hpp:66
const int32_t getMessageQueueSize() const
!< Gets the filter mask used by this instance
Definition: CanDriver.hpp:80
CanId _defaultSenderId
!< readMessage deadlock guard
Definition: CanDriver.hpp:102
int32_t _queueSize
!< The CAN socket file descriptor
Definition: CanDriver.hpp:107
virtual queue< CanMessage > readQueuedMessages()
!< Attempts to send a queue of messages
Definition: CanDriver.cpp:202
int32_t _canProtocol
!< The bit mask used to filter CAN messages
Definition: CanDriver.hpp:105
virtual int32_t sendMessageQueue(queue< CanMessage > messages, milliseconds delay=milliseconds(20), bool forceExtended=false)
!< Attempts to send a single CAN message
Definition: CanDriver.cpp:184
virtual CanMessage readMessageLock(bool const lock=true)
!< Uninitialises socketcan
Definition: CanDriver.cpp:130
const int32_t getSocketFd() const
!< Gets the amount of CAN messages found after last calling waitForMessages()
Definition: CanDriver.hpp:81
CanDriver(const string canInterface, const int32_t canProtocol, const int32_t filterMask, const CanId defaultSenderId=0)
!< Constructor
Definition: CanDriver.cpp:84
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
CanDriver & setDefaultSenderId(const CanId id)
!< Destructor
Definition: CanDriver.hpp:75
virtual bool waitForMessages(milliseconds timeout=milliseconds(3000))
!< The socket file descriptor used by this instance.
Definition: CanDriver.cpp:99
mutex _lock
!< Mutex for thread-safety.
Definition: CanDriver.hpp:110
virtual void initialiseSocketCan()
!< Attempts to set a new CAN filter mask to the BIOS
Definition: CanDriver.cpp:243
virtual ~CanDriver()
Definition: CanDriver.hpp:72
virtual int32_t sendMessage(const CanMessage message, bool forceExtended=false)
!< Attempts to read a single message from the bus
Definition: CanDriver.cpp:153
const CanId getDefaultSenderId() const
!< Sets the default sender ID
Definition: CanDriver.hpp:77
virtual void setCanFilterMask(const int32_t mask)
!< Attempts to read all queued messages from the bus
Definition: CanDriver.cpp:217
virtual void uninitialiseSocketCan()
!< Initialises socketcan
Definition: CanDriver.cpp:284
static const int32_t CAN_MAX_DATA_LENGTH
Definition: CanDriver.hpp:64
Represents a CAN message that was received.
Definition: CanMessage.hpp:55
const string getFrameData() const
Definition: CanMessage.hpp:77
const can_frame getRawFrame() const
Definition: CanMessage.hpp:78
CanMessage(const struct can_frame frame)
Definition: CanMessage.hpp:57
const CanId getCanId() const
Definition: CanMessage.hpp:76
CanException(string message, int32_t socket)
InvalidSocketException(string message, int32_t socket)
Main library namespace.
Definition: CanDriver.cpp:57
string formatString(const string &format, Args... args)
Formats a std string object.
Definition: CanDriver.hpp:131
Represents a CAN ID in a simple and easy-to-use manner.
Definition: CanId.hpp:48
CanId(const CanId &orig)
Definition: CanId.hpp:50