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