12 changed files with 0 additions and 1157 deletions
-
300core/driver/sockcanpp/CanDriver.cpp
-
154core/driver/sockcanpp/CanDriver.hpp
-
247core/driver/sockcanpp/CanId.hpp
-
88core/driver/sockcanpp/CanMessage.hpp
-
130core/driver/sockcanpp/README.md
-
57core/driver/sockcanpp/exceptions/CanCloseException.hpp
-
62core/driver/sockcanpp/exceptions/CanException.hpp
-
57core/driver/sockcanpp/exceptions/CanInitException.hpp
-
62core/driver/sockcanpp/exceptions/InvalidSocketException.hpp
-
0core/driver/socketcan/socketcan.cpp
-
0core/driver/socketcan/socketcan.hpp
-
0core/driver/socketcan/socketcan_frame.hpp
@ -1,300 +0,0 @@ |
|||||
/**
|
|
||||
* @file CanDriver.cpp |
|
||||
* @author Simon Cahill (simonc@online.de) |
|
||||
* @brief |
|
||||
* @version 0.1 |
|
||||
* @date 2020-07-01 |
|
||||
* |
|
||||
* @copyright Copyright (c) 2020 Simon Cahill |
|
||||
* |
|
||||
* |
|
||||
* Copyright 2020 Simon Cahill |
|
||||
* |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
* you may not use this file except in compliance with the License. |
|
||||
* You may obtain a copy of the License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software |
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||
* See the License for the specific language governing permissions and |
|
||||
* limitations under the License. |
|
||||
*/ |
|
||||
|
|
||||
//////////////////////////////
|
|
||||
// SYSTEM INCLUDES //
|
|
||||
//////////////////////////////
|
|
||||
|
|
||||
#include <fcntl.h>
|
|
||||
#include <linux/can.h>
|
|
||||
#include <linux/can/raw.h>
|
|
||||
#include <net/if.h>
|
|
||||
#include <sys/ioctl.h>
|
|
||||
#include <sys/socket.h>
|
|
||||
#include <sys/types.h>
|
|
||||
#include <unistd.h>
|
|
||||
|
|
||||
#include <cstdlib>
|
|
||||
#include <cstring>
|
|
||||
#include <mutex>
|
|
||||
#include <queue>
|
|
||||
#include <string>
|
|
||||
#include <thread>
|
|
||||
|
|
||||
//////////////////////////////
|
|
||||
// LOCAL INCLUDES //
|
|
||||
//////////////////////////////
|
|
||||
#include "CanDriver.hpp"
|
|
||||
#include "CanId.hpp"
|
|
||||
#include "CanMessage.hpp"
|
|
||||
#include "exceptions/CanCloseException.hpp"
|
|
||||
#include "exceptions/CanException.hpp"
|
|
||||
#include "exceptions/CanInitException.hpp"
|
|
||||
#include "exceptions/InvalidSocketException.hpp"
|
|
||||
|
|
||||
namespace sockcanpp { |
|
||||
|
|
||||
using exceptions::CanCloseException; |
|
||||
using exceptions::CanException; |
|
||||
using exceptions::CanInitException; |
|
||||
using exceptions::InvalidSocketException; |
|
||||
|
|
||||
using std::mutex; |
|
||||
using std::queue; |
|
||||
using std::string; |
|
||||
using std::strncpy; |
|
||||
using std::unique_lock; |
|
||||
using std::chrono::milliseconds; |
|
||||
using std::this_thread::sleep_for; |
|
||||
|
|
||||
//////////////////////////////////////
|
|
||||
// PUBLIC IMPLEMENTATION //
|
|
||||
//////////////////////////////////////
|
|
||||
|
|
||||
const int32_t CanDriver::CAN_MAX_DATA_LENGTH = 8; |
|
||||
const int32_t CanDriver::CAN_SOCK_RAW = CAN_RAW; |
|
||||
const int32_t CanDriver::CAN_SOCK_SEVEN = 7; |
|
||||
|
|
||||
CanDriver::CanDriver(string canInterface, int32_t canProtocol, const CanId defaultSenderId) |
|
||||
: CanDriver(canInterface, canProtocol, 0 /* match all */, defaultSenderId) {} |
|
||||
|
|
||||
CanDriver::CanDriver(const string canInterface, const int32_t canProtocol, const int32_t filterMask, const CanId defaultSenderId) |
|
||||
: _defaultSenderId(defaultSenderId), _canProtocol(canProtocol), _canInterface(canInterface), _canFilterMask(filterMask), _socketFd(-1) { |
|
||||
initialiseSocketCan(); |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Blocks until one or more CAN messages appear on the bus, or until the |
|
||||
* timeout runs out. |
|
||||
* |
|
||||
* @param timeout The time (in millis) to wait before timing out. |
|
||||
* |
|
||||
* @return true If messages are available on the bus. |
|
||||
* @return false Otherwise. |
|
||||
*/ |
|
||||
bool CanDriver::waitForMessages(milliseconds timeout) { |
|
||||
if (_socketFd < 0) { |
|
||||
throw InvalidSocketException("Invalid socket!", _socketFd); |
|
||||
} |
|
||||
|
|
||||
unique_lock<mutex> locky(_lock); |
|
||||
|
|
||||
fd_set readFileDescriptors; |
|
||||
timeval waitTime; |
|
||||
waitTime.tv_sec = timeout.count() / 1000; |
|
||||
waitTime.tv_usec = timeout.count() * 1000; |
|
||||
|
|
||||
FD_ZERO(&readFileDescriptors); |
|
||||
FD_SET(_socketFd, &readFileDescriptors); |
|
||||
_queueSize = select(_socketFd + 1, &readFileDescriptors, 0, 0, &waitTime); |
|
||||
|
|
||||
return _queueSize > 0; |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Attempts to read a message from the associated CAN bus. |
|
||||
* |
|
||||
* @return CanMessage The message read from the bus. |
|
||||
*/ |
|
||||
CanMessage CanDriver::readMessage() { return readMessageLock(); } |
|
||||
|
|
||||
/**
|
|
||||
* @brief readMessage deadlock guard, attempts to read a message from the |
|
||||
* associated CAN bus. |
|
||||
* |
|
||||
* @return CanMessage The message read from the bus. |
|
||||
*/ |
|
||||
CanMessage CanDriver::readMessageLock(bool const lock) { |
|
||||
std::unique_ptr<std::unique_lock<std::mutex>> _lockLck{nullptr}; |
|
||||
if (lock) _lockLck = std::unique_ptr<std::unique_lock<std::mutex>>{new std::unique_lock<std::mutex>{_lock}}; |
|
||||
if (0 > _socketFd) throw InvalidSocketException("Invalid socket!", _socketFd); |
|
||||
int32_t readBytes{0}; |
|
||||
can_frame canFrame; |
|
||||
memset(&canFrame, 0, sizeof(can_frame)); |
|
||||
readBytes = read(_socketFd, &canFrame, sizeof(can_frame)); |
|
||||
if (0 > readBytes) throw CanException(formatString("FAILED to read from CAN! Error: %d => %s", errno, strerror(errno)), _socketFd); |
|
||||
return CanMessage{canFrame}; |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Attempts to send a CAN message on the associated bus. |
|
||||
* |
|
||||
* @param message The message to be sent. |
|
||||
* @param forceExtended Whether or not to force use of an extended ID. |
|
||||
* |
|
||||
* @return int32_t The amount of bytes sent on the bus. |
|
||||
*/ |
|
||||
int32_t CanDriver::sendMessage(const CanMessage message, bool forceExtended) { |
|
||||
if (_socketFd < 0) { |
|
||||
throw InvalidSocketException("Invalid socket!", _socketFd); |
|
||||
} |
|
||||
|
|
||||
unique_lock<mutex> locky(_lock); |
|
||||
|
|
||||
int32_t bytesWritten = 0; |
|
||||
|
|
||||
if (message.getFrameData().size() > CAN_MAX_DATA_LENGTH) { |
|
||||
throw CanException(formatString("INVALID data length! Message must be smaller than %d bytes!", CAN_MAX_DATA_LENGTH), _socketFd); |
|
||||
} |
|
||||
|
|
||||
auto canFrame = message.getRawFrame(); |
|
||||
|
|
||||
if (forceExtended || (message.getCanId() > CAN_SFF_MASK)) { |
|
||||
canFrame.can_id |= CAN_EFF_FLAG; |
|
||||
} |
|
||||
|
|
||||
bytesWritten = write(_socketFd, (const void *)&canFrame, sizeof(canFrame)); |
|
||||
|
|
||||
if (bytesWritten == -1) { |
|
||||
throw CanException(formatString("FAILED to write data to socket! Error: %d => %s", errno, strerror(errno)), _socketFd); |
|
||||
} |
|
||||
|
|
||||
return bytesWritten; |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Attempts to send a queue of messages on the associated CAN bus. |
|
||||
* |
|
||||
* @param messages A queue containing the messages to be sent. |
|
||||
* @param delay If greater than 0, will delay the sending of the next message. |
|
||||
* @param forceExtended Whether or not to force use of an extended ID. |
|
||||
* |
|
||||
* @return int32_t The total amount of bytes sent. |
|
||||
*/ |
|
||||
int32_t CanDriver::sendMessageQueue(queue<CanMessage> messages, milliseconds delay, bool forceExtended) { |
|
||||
if (_socketFd < 0) { |
|
||||
throw InvalidSocketException("Invalid socket!", _socketFd); |
|
||||
} |
|
||||
|
|
||||
int32_t totalBytesWritten = 0; |
|
||||
|
|
||||
while (!messages.empty()) { |
|
||||
totalBytesWritten += sendMessage(messages.front(), forceExtended); |
|
||||
messages.pop(); |
|
||||
} |
|
||||
|
|
||||
return totalBytesWritten; |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Attempts to read all messages stored in the buffer for the associated |
|
||||
* CAN bus. |
|
||||
* |
|
||||
* @return queue<CanMessage> A queue containing the messages read from the bus |
|
||||
* buffer. |
|
||||
*/ |
|
||||
queue<CanMessage> CanDriver::readQueuedMessages() { |
|
||||
if (_socketFd < 0) throw InvalidSocketException("Invalid socket!", _socketFd); |
|
||||
unique_lock<mutex> locky(_lock); |
|
||||
queue<CanMessage> messages; |
|
||||
for (int32_t i = _queueSize; 0 < i; --i) messages.emplace(readMessageLock(false)); |
|
||||
return messages; |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Attempts to set the filter mask for the associated CAN bus. |
|
||||
* |
|
||||
* @param mask The bit mask to apply. |
|
||||
*/ |
|
||||
void CanDriver::setCanFilterMask(const int32_t mask) { |
|
||||
if (_socketFd < 0) { |
|
||||
throw InvalidSocketException("Invalid socket!", _socketFd); |
|
||||
} |
|
||||
|
|
||||
unique_lock<mutex> locky(_lock); |
|
||||
can_filter canFilter; |
|
||||
|
|
||||
canFilter.can_id = _defaultSenderId; |
|
||||
canFilter.can_mask = mask; |
|
||||
|
|
||||
if (setsockopt(_socketFd, SOL_CAN_RAW, CAN_RAW_FILTER, &canFilter, sizeof(canFilter)) == -1) { |
|
||||
throw CanInitException(formatString("FAILED to set CAN filter mask %x on socket %d! Error: %d => %s", mask, _socketFd, errno, strerror(errno))); |
|
||||
} |
|
||||
|
|
||||
_canFilterMask = mask; |
|
||||
} |
|
||||
|
|
||||
//////////////////////////////////////
|
|
||||
// PROTECTED IMPLEMENTATION //
|
|
||||
//////////////////////////////////////
|
|
||||
|
|
||||
/**
|
|
||||
* @brief Initialises the underlying CAN socket. |
|
||||
*/ |
|
||||
void CanDriver::initialiseSocketCan() { |
|
||||
// unique_lock<mutex> locky(_lock);
|
|
||||
|
|
||||
struct sockaddr_can address; |
|
||||
struct ifreq ifaceRequest; |
|
||||
int64_t fdOptions = 0; |
|
||||
int32_t tmpReturn; |
|
||||
|
|
||||
memset(&address, 0, sizeof(sizeof(struct sockaddr_can))); |
|
||||
memset(&ifaceRequest, 0, sizeof(sizeof(struct ifreq))); |
|
||||
|
|
||||
_socketFd = socket(PF_CAN, SOCK_RAW, _canProtocol); |
|
||||
|
|
||||
if (_socketFd == -1) { |
|
||||
throw CanInitException(formatString("FAILED to initialise socketcan! Error: %d => %s", errno, strerror(errno))); |
|
||||
} |
|
||||
|
|
||||
strcpy(ifaceRequest.ifr_name, _canInterface.c_str()); |
|
||||
|
|
||||
if ((tmpReturn = ioctl(_socketFd, SIOCGIFINDEX, &ifaceRequest)) == -1) { |
|
||||
throw CanInitException(formatString("FAILED to perform IO control operation on socket %s! Error: %d => %s", _canInterface.c_str(), errno, strerror(errno))); |
|
||||
} |
|
||||
|
|
||||
fdOptions = fcntl(_socketFd, F_GETFL); |
|
||||
fdOptions |= O_NONBLOCK; |
|
||||
tmpReturn = fcntl(_socketFd, F_SETFL, fdOptions); |
|
||||
|
|
||||
address.can_family = AF_CAN; |
|
||||
address.can_ifindex = ifaceRequest.ifr_ifindex; |
|
||||
|
|
||||
setCanFilterMask(_canFilterMask); |
|
||||
|
|
||||
if ((tmpReturn = bind(_socketFd, (struct sockaddr *)&address, sizeof(address))) == -1) { |
|
||||
throw CanInitException(formatString("FAILED to bind to socket CAN! Error: %d => %s", errno, strerror(errno))); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Closes the underlying CAN socket. |
|
||||
*/ |
|
||||
void CanDriver::uninitialiseSocketCan() { |
|
||||
unique_lock<mutex> locky(_lock); |
|
||||
|
|
||||
if (_socketFd <= 0) { |
|
||||
throw CanCloseException("Cannot close invalid socket!"); |
|
||||
} |
|
||||
|
|
||||
if (close(_socketFd) == -1) { |
|
||||
throw CanCloseException(formatString("FAILED to close CAN socket! Error: %d => %s", errno, strerror(errno))); |
|
||||
} |
|
||||
|
|
||||
_socketFd = -1; |
|
||||
} |
|
||||
|
|
||||
} // namespace sockcanpp
|
|
@ -1,154 +0,0 @@ |
|||||
/**
|
|
||||
* @file CanDriver.hpp |
|
||||
* @author Simon Cahill (simonc@online.de) |
|
||||
* @brief Contains the declarations for the SocketCAN wrapper in C++. |
|
||||
* @version 0.1 |
|
||||
* @date 2020-07-01 |
|
||||
* |
|
||||
* @copyright Copyright (c) 2020 |
|
||||
* |
|
||||
* Copyright 2020 Simon Cahill |
|
||||
* |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
* you may not use this file except in compliance with the License. |
|
||||
* You may obtain a copy of the License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software |
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||
* See the License for the specific language governing permissions and |
|
||||
* limitations under the License. |
|
||||
*/ |
|
||||
|
|
||||
#ifndef LIBSOCKCANPP_INCLUDE_CANDRIVER_HPP
|
|
||||
#define LIBSOCKCANPP_INCLUDE_CANDRIVER_HPP
|
|
||||
|
|
||||
//////////////////////////////
|
|
||||
// SYSTEM INCLUDES //
|
|
||||
//////////////////////////////
|
|
||||
#include <mutex>
|
|
||||
#include <queue>
|
|
||||
#include <string>
|
|
||||
#include <thread>
|
|
||||
|
|
||||
//////////////////////////////
|
|
||||
// LOCAL INCLUDES //
|
|
||||
//////////////////////////////
|
|
||||
#include "CanId.hpp"
|
|
||||
#include "CanMessage.hpp"
|
|
||||
|
|
||||
/**
|
|
||||
* @brief Main library namespace. |
|
||||
* |
|
||||
* This namespace contains the library's main code. |
|
||||
*/ |
|
||||
namespace sockcanpp { |
|
||||
|
|
||||
using std::mutex; |
|
||||
using std::queue; |
|
||||
using std::string; |
|
||||
using std::chrono::milliseconds; |
|
||||
|
|
||||
/**
|
|
||||
* @brief 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. |
|
||||
*/ |
|
||||
class CanDriver { |
|
||||
public: // +++ Static +++
|
|
||||
static const int32_t CAN_MAX_DATA_LENGTH; ///!< The maximum amount of bytes
|
|
||||
/// allowed in a single CAN frame
|
|
||||
static const int32_t CAN_SOCK_RAW; ///!< The raw CAN protocol
|
|
||||
static const int32_t CAN_SOCK_SEVEN; ///!< A separate CAN protocol, used by
|
|
||||
/// certain embedded device OEMs.
|
|
||||
|
|
||||
public: // +++ Constructor / Destructor +++
|
|
||||
CanDriver(const string canInterface, const int32_t canProtocol, |
|
||||
const CanId defaultSenderId = 0); ///!< Constructor
|
|
||||
CanDriver(const string canInterface, const int32_t canProtocol, const int32_t filterMask, const CanId defaultSenderId = 0); |
|
||||
CanDriver() {} |
|
||||
virtual ~CanDriver() { uninitialiseSocketCan(); } ///!< Destructor
|
|
||||
|
|
||||
public: // +++ Getter / Setter +++
|
|
||||
CanDriver &setDefaultSenderId(const CanId id) { |
|
||||
this->_defaultSenderId = id; |
|
||||
return *this; |
|
||||
} ///!< Sets the default sender ID
|
|
||||
|
|
||||
const CanId getDefaultSenderId() const { return this->_defaultSenderId; } ///!< Gets the default sender ID
|
|
||||
|
|
||||
const int32_t getFilterMask() const { return this->_canFilterMask; } ///!< Gets the filter mask used by this instance
|
|
||||
const int32_t getMessageQueueSize() const { |
|
||||
return this->_queueSize; |
|
||||
} ///!< Gets the amount of CAN messages found after last calling
|
|
||||
/// waitForMessages()
|
|
||||
const int32_t getSocketFd() const { return this->_socketFd; } ///!< The socket file descriptor used by this instance.
|
|
||||
|
|
||||
public: // +++ I/O +++
|
|
||||
virtual bool waitForMessages(milliseconds timeout = milliseconds(3000)); ///!< Waits for CAN messages to appear
|
|
||||
|
|
||||
virtual CanMessage readMessage(); ///!< Attempts to read a single message from the bus
|
|
||||
|
|
||||
virtual int32_t sendMessage(const CanMessage message, |
|
||||
bool forceExtended = false); ///!< Attempts to send a single CAN message
|
|
||||
virtual int32_t sendMessageQueue(queue<CanMessage> messages, milliseconds delay = milliseconds(20), |
|
||||
bool forceExtended = false); ///!< Attempts to send a queue of messages
|
|
||||
|
|
||||
virtual queue<CanMessage> readQueuedMessages(); ///!< Attempts to read all queued messages from the bus
|
|
||||
|
|
||||
virtual void setCanFilterMask(const int32_t mask); ///!< Attempts to set a new CAN filter
|
|
||||
/// mask to the BIOS
|
|
||||
|
|
||||
protected: // +++ Socket Management +++
|
|
||||
virtual void initialiseSocketCan(); ///!< Initialises socketcan
|
|
||||
virtual void uninitialiseSocketCan(); ///!< Uninitialises socketcan
|
|
||||
|
|
||||
private: |
|
||||
virtual CanMessage readMessageLock(bool const lock = true); ///!< readMessage deadlock guard
|
|
||||
CanId _defaultSenderId; ///!< The ID to send messages with if no other ID was
|
|
||||
/// set.
|
|
||||
|
|
||||
int32_t _canFilterMask; ///!< The bit mask used to filter CAN messages
|
|
||||
int32_t _canProtocol; ///!< The protocol used when communicating via CAN
|
|
||||
int32_t _socketFd; ///!< The CAN socket file descriptor
|
|
||||
int32_t _queueSize; ////!< The size of the message queue read by waitForMessages()
|
|
||||
|
|
||||
mutex _lock; ///!< Mutex for thread-safety.
|
|
||||
|
|
||||
string _canInterface; ///!< The CAN interface used for communication (e.g.
|
|
||||
/// can0, can1, ...)
|
|
||||
}; |
|
||||
|
|
||||
/**
|
|
||||
* @brief Formats a std string object. |
|
||||
* |
|
||||
* @remarks Yoinked from https://github.com/Beatsleigher/liblogpp :)
|
|
||||
* |
|
||||
* @tparam Args The formatting argument types. |
|
||||
* @param format The format string. |
|
||||
* @param args The format arguments (strings must be converted to C-style |
|
||||
* strings!) |
|
||||
* |
|
||||
* @return string The formatted string. |
|
||||
*/ |
|
||||
template <typename... Args> |
|
||||
string formatString(const string &format, Args... args) { |
|
||||
using std::unique_ptr; |
|
||||
auto stringSize = snprintf(NULL, 0, format.c_str(), args...) + 1; // +1 for \0
|
|
||||
unique_ptr<char[]> buffer(new char[stringSize]); |
|
||||
|
|
||||
snprintf(buffer.get(), stringSize, format.c_str(), args...); |
|
||||
|
|
||||
return string(buffer.get(), buffer.get() + stringSize - 1); // std::string handles termination for us.
|
|
||||
} |
|
||||
|
|
||||
} // namespace sockcanpp
|
|
||||
|
|
||||
#endif // LIBSOCKCANPP_INCLUDE_CANDRIVER_HPP
|
|
@ -1,247 +0,0 @@ |
|||||
/**
|
|
||||
* @file CanId.hpp |
|
||||
* @author Simon Cahill (simonc@online.de) |
|
||||
* @brief Contains the implementation of a value-type representing a CAN |
|
||||
* identifier. |
|
||||
* @version 0.1 |
|
||||
* @date 2020-07-01 |
|
||||
* |
|
||||
* @copyright Copyright (c) 2020 Simon Cahill |
|
||||
* |
|
||||
* Copyright 2020 Simon Cahill |
|
||||
* |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
* you may not use this file except in compliance with the License. |
|
||||
* You may obtain a copy of the License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software |
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||
* See the License for the specific language governing permissions and |
|
||||
* limitations under the License. |
|
||||
*/ |
|
||||
|
|
||||
#ifndef LIBSOCKPP_INCLUDE_CANID_HPP
|
|
||||
#define LIBSOCKPP_INCLUDE_CANID_HPP
|
|
||||
|
|
||||
//////////////////////////////
|
|
||||
// SYSTEM INCLUDES //
|
|
||||
//////////////////////////////
|
|
||||
#include <linux/can.h>
|
|
||||
|
|
||||
#include <bitset>
|
|
||||
#include <cmath>
|
|
||||
#include <exception>
|
|
||||
|
|
||||
namespace sockcanpp { |
|
||||
|
|
||||
using std::bitset; |
|
||||
using std::error_code; |
|
||||
using std::exception; |
|
||||
using std::generic_category; |
|
||||
using std::system_error; |
|
||||
|
|
||||
/**
|
|
||||
* @brief Represents a CAN ID in a simple and easy-to-use manner. |
|
||||
*/ |
|
||||
struct CanId { |
|
||||
public: // +++ Constructors +++
|
|
||||
CanId(const CanId &orig) |
|
||||
: _identifier(orig._identifier), |
|
||||
_isErrorFrame(orig._isErrorFrame), |
|
||||
_isRemoteTransmissionRequest(orig._isRemoteTransmissionRequest), |
|
||||
_isStandardFrameId(orig._isStandardFrameId), |
|
||||
_isExtendedFrameId(orig._isExtendedFrameId) { /* copy */ |
|
||||
} |
|
||||
|
|
||||
CanId(const uint32_t identifier) : _identifier(identifier) { |
|
||||
// TODO: Switch to using bitmasks!
|
|
||||
|
|
||||
if (isValidIdentifier(identifier)) { |
|
||||
if (((int32_t)log2(identifier) + 1) < 11) { |
|
||||
_isStandardFrameId = true; |
|
||||
} else { |
|
||||
_isExtendedFrameId = true; |
|
||||
} |
|
||||
} else if (isErrorFrame(identifier)) { |
|
||||
_isErrorFrame = true; |
|
||||
} else if (isRemoteTransmissionRequest(identifier)) { |
|
||||
_isRemoteTransmissionRequest = true; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
CanId() : _identifier(0), _isStandardFrameId(true) {} |
|
||||
|
|
||||
public: // +++ Operators +++
|
|
||||
operator int16_t() const { |
|
||||
return isStandardFrameId() ? (int16_t)_identifier : throw system_error(error_code(0xbad1d, generic_category()), "INVALID CAST: ID is extended or invalid!"); |
|
||||
} |
|
||||
operator uint16_t() const { |
|
||||
return isStandardFrameId() ? (uint16_t)_identifier |
|
||||
: throw system_error(error_code(0xbad1d, generic_category()), "INVALID CAST: ID is extended or invalid!"); |
|
||||
} |
|
||||
operator int32_t() const { return _identifier; } |
|
||||
operator uint32_t() const { return _identifier; } |
|
||||
|
|
||||
CanId operator&(CanId &x) const { return _identifier & x._identifier; } |
|
||||
CanId operator&(const CanId x) const { return _identifier & x._identifier; } |
|
||||
CanId operator&(const int16_t x) const { return _identifier & x; } |
|
||||
CanId operator&(const uint16_t x) const { return _identifier & x; } |
|
||||
CanId operator&(const int32_t x) const { return _identifier & x; } |
|
||||
CanId operator&(const uint32_t x) const { return _identifier & x; } |
|
||||
CanId operator&(const int64_t x) const { return _identifier & x; } |
|
||||
CanId operator&(const uint64_t x) const { return _identifier & x; } |
|
||||
|
|
||||
CanId operator|(CanId &x) const { return _identifier | x._identifier; } |
|
||||
CanId operator|(const CanId x) const { return _identifier | x._identifier; } |
|
||||
CanId operator|(const int16_t x) const { return _identifier | x; } |
|
||||
CanId operator|(const uint16_t x) const { return _identifier | x; } |
|
||||
CanId operator|(const int32_t x) const { return _identifier | x; } |
|
||||
CanId operator|(const uint32_t x) const { return _identifier | x; } |
|
||||
CanId operator|(const int64_t x) const { return _identifier | x; } |
|
||||
CanId operator|(const uint64_t x) const { return _identifier | x; } |
|
||||
|
|
||||
bool operator==(CanId &x) const { return _identifier == x._identifier; } |
|
||||
bool operator==(const CanId &x) const { return _identifier == x._identifier; } |
|
||||
bool operator==(const int16_t x) const { return int16_t(_identifier) == x; } |
|
||||
bool operator==(const uint16_t x) const { return uint16_t(_identifier) == x; } |
|
||||
bool operator==(const int32_t x) const { return int32_t(_identifier) == x; } |
|
||||
bool operator==(const uint32_t x) const { return uint32_t(_identifier) == x; } |
|
||||
bool operator==(const int64_t x) const { return (x > UINT32_MAX || x < INT32_MIN) ? false : x == int64_t(_identifier); } |
|
||||
bool operator==(const uint64_t x) const { return x > UINT32_MAX ? false : x == uint64_t(_identifier); } |
|
||||
bool operator!=(CanId &x) const { return _identifier != x._identifier; } |
|
||||
bool operator!=(const CanId &x) const { return _identifier != x._identifier; } |
|
||||
bool operator!=(const int16_t x) const { return int16_t(_identifier) != x; } |
|
||||
bool operator!=(const uint16_t x) const { return uint16_t(_identifier) != x; } |
|
||||
bool operator!=(const int32_t x) const { return int32_t(_identifier) != x; } |
|
||||
bool operator!=(const uint32_t x) const { return uint32_t(_identifier) != x; } |
|
||||
bool operator!=(const int64_t x) const { return (x > UINT32_MAX || x < INT32_MIN) ? false : x != _identifier; } |
|
||||
bool operator!=(const uint64_t x) const { return x > UINT32_MAX ? false : x != _identifier; } |
|
||||
|
|
||||
bool operator<(CanId &x) const { return x._identifier < _identifier; } |
|
||||
bool operator<(int32_t x) const { return x < int32_t(_identifier); } |
|
||||
bool operator<(uint32_t x) const { return x < uint32_t(_identifier); } |
|
||||
bool operator<(int16_t x) const { return x < int16_t(_identifier); } |
|
||||
bool operator<(uint16_t x) const { return x < uint16_t(_identifier); } |
|
||||
bool operator<=(CanId &x) const { return x._identifier <= _identifier; } |
|
||||
bool operator>(CanId &x) const { return x._identifier > _identifier; } |
|
||||
bool operator>(int32_t x) const { return x > int32_t(_identifier); } |
|
||||
bool operator>(uint32_t x) const { return x > uint32_t(_identifier); } |
|
||||
bool operator>(int16_t x) const { return x > int16_t(_identifier); } |
|
||||
bool operator>(uint16_t x) const { return x > uint16_t(_identifier); } |
|
||||
bool operator>=(CanId &x) const { return x._identifier >= _identifier; } |
|
||||
bool operator<(const CanId &x) const { return x._identifier < _identifier; } |
|
||||
bool operator<=(const CanId &x) const { return x._identifier <= _identifier; } |
|
||||
bool operator>(const CanId &x) const { return x._identifier > _identifier; } |
|
||||
bool operator>=(const CanId &x) const { return x._identifier >= _identifier; } |
|
||||
|
|
||||
CanId operator=(const int32_t val) { |
|
||||
uint32_t tmpVal = val; |
|
||||
auto tmp = |
|
||||
(isValidIdentifier(tmpVal) ? CanId(val) : throw system_error(error_code(0x5421, generic_category()), "INVALID CAST: ID is extended or invalid!")); |
|
||||
return tmp; |
|
||||
} |
|
||||
|
|
||||
CanId operator=(const uint32_t val) { |
|
||||
uint32_t tmp = val; |
|
||||
return (isValidIdentifier(tmp) ? CanId(val) : throw system_error(error_code(0x5421, generic_category()), "INVALID CAST: ID is extended or invalid!")); |
|
||||
} |
|
||||
|
|
||||
CanId operator=(const int64_t val) { return operator=((int32_t)val); } |
|
||||
|
|
||||
CanId operator+(CanId &x) const { return _identifier + x._identifier; } |
|
||||
CanId operator+(const CanId &x) const { return _identifier + x._identifier; } |
|
||||
CanId operator+(const int16_t x) const { return _identifier + x; } |
|
||||
CanId operator+(const uint16_t x) const { return _identifier + x; } |
|
||||
CanId operator+(const int32_t x) const { return _identifier + x; } |
|
||||
CanId operator+(const uint32_t x) const { return _identifier + x; } |
|
||||
CanId operator+(const int64_t x) const { return _identifier + x; } |
|
||||
CanId operator+(const uint64_t x) const { return _identifier + x; } |
|
||||
|
|
||||
CanId operator-(CanId &x) const { return _identifier - x._identifier; } |
|
||||
CanId operator-(const CanId &x) const { return _identifier - x._identifier; } |
|
||||
CanId operator-(const int16_t x) const { return _identifier - x; } |
|
||||
CanId operator-(const uint16_t x) const { return _identifier - x; } |
|
||||
CanId operator-(const int32_t x) const { return _identifier - x; } |
|
||||
CanId operator-(const uint32_t x) const { return _identifier - x; } |
|
||||
CanId operator-(const int64_t x) const { return _identifier - x; } |
|
||||
CanId operator-(const uint64_t x) const { return _identifier - x; } |
|
||||
|
|
||||
public: // +++ Validity Checks +++
|
|
||||
/**
|
|
||||
* @brief Indicates whether or not a given integer is a valid CAN identifier. |
|
||||
* |
|
||||
* @param value The integer to check. |
|
||||
* |
|
||||
* @return true If value is a valid CAN identifier. |
|
||||
* @return false Otherwise. |
|
||||
*/ |
|
||||
static bool isValidIdentifier(uint32_t value) { |
|
||||
int32_t tmpValue = ((int32_t)log2(value) + 2); // Get bit count
|
|
||||
|
|
||||
// Check for extended frame flag
|
|
||||
if (tmpValue >= 29) { |
|
||||
value = (value & CAN_EFF_FLAG) ? (value & CAN_EFF_MASK) : (value & CAN_SFF_MASK); |
|
||||
tmpValue = ((int32_t)log2(value) + 1); // Get bit count again
|
|
||||
} |
|
||||
|
|
||||
return (value == 0) /* Default value, also valid ID */ || ((tmpValue <= 29 && tmpValue > 0)); |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Indicates whether or not a given integer contains the error frame |
|
||||
* flag or not. |
|
||||
* |
|
||||
* @param value The integer to check. |
|
||||
* |
|
||||
* @return true If value has the error frame flag (bit) set to 1. |
|
||||
* @return false Otherwise. |
|
||||
*/ |
|
||||
static bool isErrorFrame(uint32_t value) { |
|
||||
try { |
|
||||
return bitset<sizeof(int32_t)>(value).test(29); |
|
||||
} catch (...) { |
|
||||
return false; /* Brute-force, but works. */ |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Indicates whether the received frame is a remote transmission |
|
||||
* request. |
|
||||
* |
|
||||
* @param value The integer to check. |
|
||||
* |
|
||||
* @return true If the frame is a remote transmission request. |
|
||||
* @return false Otherwise. |
|
||||
*/ |
|
||||
static bool isRemoteTransmissionRequest(uint32_t value) { |
|
||||
try { |
|
||||
return bitset<sizeof(int32_t)>(value).test(30); |
|
||||
} catch (...) { |
|
||||
return false; /* Brute-force, but works. */ |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public: // +++ Getters +++
|
|
||||
bool hasErrorFrameFlag() const { return _isErrorFrame; } |
|
||||
bool hasRtrFrameFlag() const { return _isRemoteTransmissionRequest; } |
|
||||
bool isStandardFrameId() const { return _isStandardFrameId; } |
|
||||
bool isExtendedFrameId() const { return _isExtendedFrameId; } |
|
||||
|
|
||||
public: // +++ Equality Checks +++
|
|
||||
bool equals(CanId otherId) const { return *this == otherId; } |
|
||||
|
|
||||
private: // +++ Variables +++
|
|
||||
bool _isErrorFrame = false; |
|
||||
bool _isRemoteTransmissionRequest = false; |
|
||||
bool _isStandardFrameId = false; |
|
||||
bool _isExtendedFrameId = false; |
|
||||
|
|
||||
uint32_t _identifier = 0; |
|
||||
}; |
|
||||
|
|
||||
} // namespace sockcanpp
|
|
||||
|
|
||||
#endif // LIBSOCKPP_INCLUDE_CANID_HPP
|
|
@ -1,88 +0,0 @@ |
|||||
/**
|
|
||||
* @file CanMessage.hpp |
|
||||
* @author Simon Cahill (simonc@online.de) |
|
||||
* @brief Contains the implementation of a CAN message representation in C++. |
|
||||
* @version 0.1 |
|
||||
* @date 2020-07-01 |
|
||||
* |
|
||||
* @copyright Copyright (c) 2020 Simon Cahill |
|
||||
* |
|
||||
* Copyright 2020 Simon Cahill |
|
||||
* |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
* you may not use this file except in compliance with the License. |
|
||||
* You may obtain a copy of the License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software |
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||
* See the License for the specific language governing permissions and |
|
||||
* limitations under the License. |
|
||||
*/ |
|
||||
|
|
||||
#ifndef LIBSOCKCANPP_INCLUDE_CANMESSAGE_HPP
|
|
||||
#define LIBSOCKCANPP_INCLUDE_CANMESSAGE_HPP
|
|
||||
|
|
||||
//////////////////////////////
|
|
||||
// SYSTEM INCLUDES //
|
|
||||
//////////////////////////////
|
|
||||
#include <linux/can.h>
|
|
||||
|
|
||||
#include <cstring>
|
|
||||
#include <exception>
|
|
||||
#include <string>
|
|
||||
#include <thread>
|
|
||||
|
|
||||
//////////////////////////////
|
|
||||
// LOCAL INCLUDES //
|
|
||||
//////////////////////////////
|
|
||||
#include "CanId.hpp"
|
|
||||
|
|
||||
namespace sockcanpp { |
|
||||
|
|
||||
using std::error_code; |
|
||||
using std::generic_category; |
|
||||
using std::memcpy; |
|
||||
using std::string; |
|
||||
using std::system_error; |
|
||||
|
|
||||
/**
|
|
||||
* @brief Represents a CAN message that was received. |
|
||||
*/ |
|
||||
class CanMessage { |
|
||||
public: // +++ Constructor / Destructor +++
|
|
||||
CanMessage(const struct can_frame frame) : _canIdentifier(frame.can_id), _frameData((const char *)frame.data, frame.can_dlc), _rawFrame(frame) {} |
|
||||
|
|
||||
CanMessage(const CanId canId, const string frameData) : _canIdentifier(canId), _frameData(frameData) { |
|
||||
if (frameData.size() > 8) { |
|
||||
throw system_error(error_code(0xbadd1c, generic_category()), "Payload too big!"); |
|
||||
} |
|
||||
|
|
||||
struct can_frame rawFrame; |
|
||||
rawFrame.can_id = canId; |
|
||||
memcpy(rawFrame.data, frameData.data(), frameData.size()); |
|
||||
rawFrame.can_dlc = frameData.size(); |
|
||||
|
|
||||
_rawFrame = rawFrame; |
|
||||
} |
|
||||
|
|
||||
virtual ~CanMessage() {} |
|
||||
|
|
||||
public: // +++ Getters +++
|
|
||||
const CanId getCanId() const { return this->_canIdentifier; } |
|
||||
const string getFrameData() const { return this->_frameData; } |
|
||||
const can_frame getRawFrame() const { return this->_rawFrame; } |
|
||||
|
|
||||
private: |
|
||||
CanId _canIdentifier; |
|
||||
|
|
||||
string _frameData; |
|
||||
|
|
||||
struct can_frame _rawFrame; |
|
||||
}; |
|
||||
|
|
||||
} // namespace sockcanpp
|
|
||||
|
|
||||
#endif // LIBSOCKCANPP_INCLUDE_CANMESSAGE_HPP
|
|
@ -1,130 +0,0 @@ |
|||||
|
|
||||
``` |
|
||||
BaseOn: |
|
||||
https://github.com/SimonCahill/libsockcanpp |
|
||||
4d0e6a3e679a34dee4449a9d22b7f794a3cf9871 |
|
||||
|
|
||||
localGit |
|
||||
http://192.168.1.3:3000/z3rd_lib/libsockcanpp |
|
||||
|
|
||||
Demo: |
|
||||
http://192.168.1.3:3000/z3rd_lib/libsockcanpp/src/branch/master/test/src/Main.cpp |
|
||||
``` |
|
||||
|
|
||||
|
|
||||
# Usage |
|
||||
```cpp |
|
||||
/** |
|
||||
* @file Main.cpp |
|
||||
* @author Simon Cahill (simonc@online.de) |
|
||||
* @brief Contains the implementation of a test application using this library. |
|
||||
* @version 0.1 |
|
||||
* @date 2020-07-02 |
|
||||
* |
|
||||
* @copyright Copyright (c) 2020 Simon Cahill |
|
||||
* |
|
||||
* Copyright 2020 Simon Cahill |
|
||||
* |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
* you may not use this file except in compliance with the License. |
|
||||
* You may obtain a copy of the License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software |
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||
* See the License for the specific language governing permissions and |
|
||||
* limitations under the License. |
|
||||
*/ |
|
||||
|
|
||||
#include <iostream> |
|
||||
#include <string> |
|
||||
|
|
||||
#include <CanDriver.hpp> |
|
||||
#include <exceptions/CanException.hpp> |
|
||||
#include <exceptions/CanInitException.hpp> |
|
||||
#include <exceptions/InvalidSocketException.hpp> |
|
||||
|
|
||||
using sockcanpp::CanDriver; |
|
||||
using sockcanpp::CanId; |
|
||||
using sockcanpp::exceptions::CanException; |
|
||||
using sockcanpp::exceptions::CanInitException; |
|
||||
using sockcanpp::exceptions::InvalidSocketException; |
|
||||
using sockcanpp::CanMessage; |
|
||||
|
|
||||
using std::cerr; |
|
||||
using std::cout; |
|
||||
using std::endl; |
|
||||
using std::string; |
|
||||
|
|
||||
void printHelp(string); |
|
||||
|
|
||||
int main(int32_t argCount, char** argValues) { |
|
||||
int32_t desiredCanSocket = 0; |
|
||||
string canInterface; |
|
||||
|
|
||||
if (argCount > 2) { |
|
||||
for (int32_t i = 1; i < argCount; i++) { |
|
||||
if (argValues[i] == "--help" || argValues[i] == "-h") { |
|
||||
printHelp(argValues[0]); |
|
||||
return 0; |
|
||||
} else if (argValues[i] == "-protocol") { |
|
||||
desiredCanSocket = atoi(argValues[i + 1]); |
|
||||
i += 1; |
|
||||
continue; |
|
||||
} else if (argValues[i] == "-iface") { |
|
||||
canInterface = (argValues[i + 1]); |
|
||||
i += 1; |
|
||||
continue; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (desiredCanSocket <= 0) |
|
||||
desiredCanSocket = CanDriver::CAN_SOCK_RAW; |
|
||||
if (canInterface == "") |
|
||||
canInterface = "can0"; |
|
||||
|
|
||||
CanDriver* canDriver; |
|
||||
try { |
|
||||
canDriver = new CanDriver(canInterface, CAN_RAW); |
|
||||
} catch (CanInitException& ex) { |
|
||||
cerr << "An error occurred while initialising CanDriver: " << ex.what() << endl; |
|
||||
delete canDriver; |
|
||||
return -1; |
|
||||
} |
|
||||
|
|
||||
while (true) { |
|
||||
printf("Writing test message:\n"); |
|
||||
try { canDriver->sendMessage(CanMessage(0x555, "abcdefg8")); } |
|
||||
catch (CanException& ex) { cerr << "Failed to send test message! " << ex.what() << endl; } |
|
||||
catch (InvalidSocketException& ex) { cerr << "Failed to send test message! " << ex.what() << endl; } |
|
||||
|
|
||||
printf("Reading messages\n"); |
|
||||
if (!canDriver->waitForMessages()) continue; |
|
||||
|
|
||||
cout << "Reading queue..." << endl; |
|
||||
auto canMessages = canDriver->readQueuedMessages(); |
|
||||
while (!canMessages.empty()) { |
|
||||
auto msg = canMessages.front(); |
|
||||
canMessages.pop(); |
|
||||
|
|
||||
cout << "CAN ID: " << (int32_t)msg.getCanId() << endl |
|
||||
<< "CAN data: "; |
|
||||
for (auto byte : msg.getFrameData()) |
|
||||
cout << std::hex << byte << " "; |
|
||||
cout << endl; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void printHelp(string appname) { |
|
||||
cout << appname << endl << endl |
|
||||
<< "-h\t\tPrints this menu" << endl |
|
||||
<< "--help\t\tPrints this menu" << endl |
|
||||
<< "-protocol <protocol_num>" << endl |
|
||||
<< "-iface <can_iface>" << endl; |
|
||||
} |
|
||||
``` |
|
||||
|
|
@ -1,57 +0,0 @@ |
|||||
/**
|
|
||||
* @file CanCloseException.hpp |
|
||||
* @author Simon Cahill (simonc@online.de) |
|
||||
* @brief Contains the implementation of an exception that may be thrown when an |
|
||||
* error occurs while closing a CAN socket. |
|
||||
* @version 0.1 |
|
||||
* @date 2020-07-02 |
|
||||
* |
|
||||
* @copyright Copyright (c) 2020 Simon Cahill |
|
||||
* |
|
||||
* Copyright 2020 Simon Cahill |
|
||||
* |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
* you may not use this file except in compliance with the License. |
|
||||
* You may obtain a copy of the License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software |
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||
* See the License for the specific language governing permissions and |
|
||||
* limitations under the License. |
|
||||
*/ |
|
||||
|
|
||||
#ifndef LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANCLOSEEXCEPTION_HPP
|
|
||||
#define LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANCLOSEEXCEPTION_HPP
|
|
||||
|
|
||||
#include <exception>
|
|
||||
#include <string>
|
|
||||
|
|
||||
namespace sockcanpp { |
|
||||
namespace exceptions { |
|
||||
|
|
||||
using std::exception; |
|
||||
using std::string; |
|
||||
|
|
||||
/**
|
|
||||
* @brief An exception that may be thrown when an error occurs while closing a |
|
||||
* CAN socket. |
|
||||
*/ |
|
||||
class CanCloseException : public exception { |
|
||||
public: // +++ Constructor / Destructor +++
|
|
||||
CanCloseException(string message) : _message(message) {} |
|
||||
~CanCloseException() {} |
|
||||
|
|
||||
public: // +++ Overrides +++
|
|
||||
const char *what() { return _message.c_str(); } |
|
||||
|
|
||||
private: |
|
||||
string _message; |
|
||||
}; |
|
||||
|
|
||||
} // namespace exceptions
|
|
||||
} // namespace sockcanpp
|
|
||||
|
|
||||
#endif // LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANCLOSEEXCEPTION_HPP
|
|
@ -1,62 +0,0 @@ |
|||||
/**
|
|
||||
* @file CanException.hpp |
|
||||
* @author Simon Cahill (simonc@online.de) |
|
||||
* @brief Contains the implementation of a general-purpose exception which may |
|
||||
* be thrown when an error occurs when performing IO on a CAN socket. |
|
||||
* @version 0.1 |
|
||||
* @date 2020-07-02 |
|
||||
* |
|
||||
* @copyright Copyright (c) 2020 Simon Cahill |
|
||||
* |
|
||||
* Copyright 2020 Simon Cahill |
|
||||
* |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
* you may not use this file except in compliance with the License. |
|
||||
* You may obtain a copy of the License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software |
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||
* See the License for the specific language governing permissions and |
|
||||
* limitations under the License. |
|
||||
*/ |
|
||||
|
|
||||
#ifndef LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANEXCEPTION_HPP
|
|
||||
#define LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANEXCEPTION_HPP
|
|
||||
|
|
||||
#include <exception>
|
|
||||
#include <string>
|
|
||||
|
|
||||
namespace sockcanpp { |
|
||||
namespace exceptions { |
|
||||
|
|
||||
using std::exception; |
|
||||
using std::string; |
|
||||
|
|
||||
/**
|
|
||||
* @brief An exception that may be thrown when an error occurs while closing a |
|
||||
* CAN socket. |
|
||||
*/ |
|
||||
class CanException : public exception { |
|
||||
public: // +++ Constructor / Destructor +++
|
|
||||
CanException(string message, int32_t socket) : _message(message), _socket(socket) {} |
|
||||
~CanException() {} |
|
||||
|
|
||||
public: // +++ Overrides +++
|
|
||||
const char *what() { return _message.c_str(); } |
|
||||
|
|
||||
public: // +++ Getter +++
|
|
||||
const int32_t getSocket() const { return _socket; } |
|
||||
|
|
||||
private: |
|
||||
int32_t _socket; |
|
||||
|
|
||||
string _message; |
|
||||
}; |
|
||||
|
|
||||
} // namespace exceptions
|
|
||||
} // namespace sockcanpp
|
|
||||
|
|
||||
#endif // LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANEXCEPTION_HPP
|
|
@ -1,57 +0,0 @@ |
|||||
/**
|
|
||||
* @file CanInitException.hpp |
|
||||
* @author Simon Cahill (simonc@online.de) |
|
||||
* @brief Contains the implementation of an exception that is thrown when a CAN |
|
||||
* socket couldn't be inintialised. |
|
||||
* @version 0.1 |
|
||||
* @date 2020-07-02 |
|
||||
* |
|
||||
* @copyright Copyright (c) 2020 Simon Cahill |
|
||||
* |
|
||||
* Copyright 2020 Simon Cahill |
|
||||
* |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
* you may not use this file except in compliance with the License. |
|
||||
* You may obtain a copy of the License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software |
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||
* See the License for the specific language governing permissions and |
|
||||
* limitations under the License. |
|
||||
*/ |
|
||||
|
|
||||
#ifndef LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANINITEXCEPTION_HPP
|
|
||||
#define LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANINITEXCEPTION_HPP
|
|
||||
|
|
||||
#include <exception>
|
|
||||
#include <string>
|
|
||||
|
|
||||
namespace sockcanpp { |
|
||||
namespace exceptions { |
|
||||
|
|
||||
using std::exception; |
|
||||
using std::string; |
|
||||
|
|
||||
/**
|
|
||||
* @brief An exception that may be thrown when an error occurred while |
|
||||
* initialising a CAN socket. |
|
||||
*/ |
|
||||
class CanInitException : public exception { |
|
||||
public: // +++ Constructor / Destructor +++
|
|
||||
CanInitException(string message) : _message(message) {} |
|
||||
virtual ~CanInitException() {} |
|
||||
|
|
||||
public: // +++ Override +++
|
|
||||
const char *what() { return _message.c_str(); } |
|
||||
|
|
||||
private: |
|
||||
string _message; |
|
||||
}; |
|
||||
|
|
||||
} // namespace exceptions
|
|
||||
} // namespace sockcanpp
|
|
||||
|
|
||||
#endif // LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANINITEXCEPTION_HPP
|
|
@ -1,62 +0,0 @@ |
|||||
/**
|
|
||||
* @file InvalidSocketException.hpp |
|
||||
* @author Simon Cahill (simonc@online.de) |
|
||||
* @brief Contains the implementation of an exception that may be thrown when an |
|
||||
* invalid CAN socket is detected. |
|
||||
* @version 0.1 |
|
||||
* @date 2020-07-02 |
|
||||
* |
|
||||
* @copyright Copyright (c) 2020 Simon Cahill |
|
||||
* |
|
||||
* Copyright 2020 Simon Cahill |
|
||||
* |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
* you may not use this file except in compliance with the License. |
|
||||
* You may obtain a copy of the License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software |
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||
* See the License for the specific language governing permissions and |
|
||||
* limitations under the License. |
|
||||
*/ |
|
||||
|
|
||||
#ifndef LIBSOCKCANPP_INCLUDE_EXCEPTIONS_INVALIDSOCKETEXCEPTION_HPP
|
|
||||
#define LIBSOCKCANPP_INCLUDE_EXCEPTIONS_INVALIDSOCKETEXCEPTION_HPP
|
|
||||
|
|
||||
#include <exception>
|
|
||||
#include <string>
|
|
||||
|
|
||||
namespace sockcanpp { |
|
||||
namespace exceptions { |
|
||||
|
|
||||
using std::exception; |
|
||||
using std::string; |
|
||||
|
|
||||
/**
|
|
||||
* @brief An exception that may be thrown when an error occurs while closing a |
|
||||
* CAN socket. |
|
||||
*/ |
|
||||
class InvalidSocketException : public exception { |
|
||||
public: // +++ Constructor / Destructor +++
|
|
||||
InvalidSocketException(string message, int32_t socket) : _message(message), _socket(socket) {} |
|
||||
~InvalidSocketException() {} |
|
||||
|
|
||||
public: // +++ Overrides +++
|
|
||||
const char *what() { return _message.c_str(); } |
|
||||
|
|
||||
public: // +++ Getter +++
|
|
||||
const int32_t getSocket() const { return _socket; } |
|
||||
|
|
||||
private: |
|
||||
int32_t _socket; |
|
||||
|
|
||||
string _message; |
|
||||
}; |
|
||||
|
|
||||
} // namespace exceptions
|
|
||||
} // namespace sockcanpp
|
|
||||
|
|
||||
#endif // LIBSOCKCANPP_INCLUDE_EXCEPTIONS_INVALIDSOCKETEXCEPTION_HPP
|
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue