Skip to content

Commit

Permalink
feat: better structure
Browse files Browse the repository at this point in the history
  • Loading branch information
Rui Rocha authored and rui-rocha-42 committed Jan 27, 2025
1 parent 129838a commit 9e12a64
Show file tree
Hide file tree
Showing 17 changed files with 271 additions and 43 deletions.
3 changes: 2 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"xaver.clang-format",
"BazelBuild.vscode-bazel",
"llvm-vs-code-extensions.vscode-clangd",
"ms-azuretools.vscode-docker"
"ms-azuretools.vscode-docker",
"cschlosser.doxdocgen"
],
"settings": {
"remote.autoForwardPorts": false
Expand Down
7 changes: 4 additions & 3 deletions com-middleware/BUILD
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
cc_binary(
name = "bin",
srcs = ["main.cpp"],
srcs = ["src/main.cpp"],
features = ["warnings_critical_code_gcc"],
linkopts = [
"-lzmq",
],
deps = [
"//com-middleware/can",
"//com-middleware/exceptions",
"//com-middleware/src/can",
"//com-middleware/src/exceptions",
"//com-middleware/src/mq",
"@cppzmq",
],
)
6 changes: 3 additions & 3 deletions com-middleware/can/BUILD → com-middleware/src/can/BUILD
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
cc_library(
name = "can",
srcs = ["CanDriver.cpp"],
hdrs = ["CanDriver.hpp"],
srcs = glob(["*.cpp"]),
hdrs = glob(["*.hpp"]),
features = ["warnings_critical_code_gcc"],
visibility = ["//visibility:public"],
deps = ["//com-middleware/exceptions"],
deps = ["//com-middleware/src/exceptions"],
)
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
#include <cstring>
#include <iostream>

#include "com-middleware/exceptions/CanCloseException.hpp"
#include "com-middleware/exceptions/CanInitException.hpp"
#include "com-middleware/src/exceptions/CanCloseException.hpp"
#include "com-middleware/src/exceptions/CanInitException.hpp"

namespace candriver {

Expand All @@ -19,6 +19,14 @@ CanDriver::CanDriver(std::string can_interface, int32_t timeout_s)
initializeCan();
};

CanDriver::~CanDriver() {
try {
uninitializeCan();
} catch (const std::exception &exception) {
std::cout << exception.what() << "\n";
}
};

void CanDriver::initializeCan() {
if (m_canInterface.empty()) {
throw exceptions::CanInitException("Can interface is empty");
Expand All @@ -38,6 +46,7 @@ void CanDriver::initializeCan() {
// Setting the can interface
strcpy(ifr.ifr_name, m_canInterface.c_str());
// To determine the interface index an appropriate ioctl() has to be used (0 for all)
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
ioctl(m_can_socket_fd, SIOCGIFINDEX, &ifr);

memset(&addr, 0, sizeof(addr));
Expand All @@ -63,7 +72,7 @@ void CanDriver::uninitializeCan() const {
}
}

auto CanDriver::readMessage(void *buffer) const -> int32_t {
return static_cast<int32_t>(read(m_can_socket_fd, buffer, sizeof(struct can_frame)));
auto CanDriver::receive(can_frame *frame) const -> int32_t {
return static_cast<int32_t>(::read(m_can_socket_fd, frame, sizeof(can_frame)));
}
} // namespace candriver
} // namespace candriver
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
#ifndef CAN_DRIVER_HPP
#define CAN_DRIVER_HPP

#include <linux/can.h>

#include <string>

#include "ICanDriver.hpp"

namespace candriver {

class CanDriver {
class CanDriver : public ICanDriver {
private:
std::string m_canInterface;
int32_t m_timeout_s;
int32_t m_can_socket_fd{};

public:
CanDriver(std::string can_interface, int32_t timeout_s);
virtual ~CanDriver() noexcept(false) { uninitializeCan(); }
~CanDriver() override;
CanDriver() = delete;
CanDriver(const CanDriver&) = default;
auto operator=(const CanDriver&) -> CanDriver& = default;
CanDriver(CanDriver&&) = default;
auto operator=(CanDriver&&) -> CanDriver& = default;

private:
/**
Expand All @@ -28,8 +37,8 @@ class CanDriver {
void uninitializeCan() const;

public:
auto readMessage(void* buffer) const -> int32_t;
auto receive(can_frame* frame) const -> int32_t override;
};
} // namespace candriver

#endif
#endif
25 changes: 25 additions & 0 deletions com-middleware/src/can/ICanDriver.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <linux/can.h>

#include <cstdint>

/**
* @brief Asbtracts the Linux CAN Socket logic
*
*/
class ICanDriver {
public:
ICanDriver() = default;
ICanDriver(const ICanDriver&) = default;
auto operator=(const ICanDriver&) -> ICanDriver& = default;
ICanDriver(ICanDriver&&) = default;
auto operator=(ICanDriver&&) -> ICanDriver& = default;
virtual ~ICanDriver() = default;

/**
* @brief Receives CAN message
*
* @param frame CAN frame
* @return int32_t number of bytes received
*/
virtual auto receive(can_frame* frame) const -> int32_t = 0;
};
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ class CanCloseException : public exception {

} // namespace candriver::exceptions

#endif // CAN_DRIVER_EXCEPTIONS_CANCLOSEEXCEPTION_HPP
#endif // CAN_DRIVER_EXCEPTIONS_CANCLOSEEXCEPTION_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ class CanInitException : public exception {

} // namespace candriver::exceptions

#endif // CAN_DRIVER_EXCEPTIONS_CANINITEXCEPTION_HPP
#endif // CAN_DRIVER_EXCEPTIONS_CANINITEXCEPTION_HPP
51 changes: 26 additions & 25 deletions com-middleware/main.cpp → com-middleware/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,30 @@
#include <zmq.hpp>

#include "can/CanDriver.hpp"
#include "mq/ZeroMQPublisher.hpp"

namespace {
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
volatile std::sig_atomic_t interrupted{0};
} // namespace

void signal_handler(int signum) {
void signalHandler(int signum) {
(void)signum; // ignore unused variable
interrupted = 1;
}

void catch_signals() {
(void)std::signal(SIGINT, signal_handler);
(void)std::signal(SIGTERM, signal_handler);
(void)std::signal(SIGSEGV, signal_handler);
(void)std::signal(SIGABRT, signal_handler);
void catchSignals() {
(void)std::signal(SIGINT, signalHandler);
(void)std::signal(SIGTERM, signalHandler);
(void)std::signal(SIGSEGV, signalHandler);
(void)std::signal(SIGABRT, signalHandler);
}

auto main(int argc, char **argv) -> int {
int opt{};
std::string interface = "can0";

// NOLINTNEXTLINE(concurrency-mt-unsafe)
while ((opt = getopt(argc, argv, "i:")) != -1) { // "i:" means -i takes an argument
switch (opt) {
case 'i':
Expand All @@ -52,25 +54,28 @@ auto main(int argc, char **argv) -> int {
std::unique_ptr<candriver::CanDriver> can;
try {
can = std::make_unique<candriver::CanDriver>(interface, 5);
} catch (const std::exception &myCustomException) {
std::cout << myCustomException.what() << std::endl;
} catch (const std::exception &exception) {
std::cout << exception.what() << "\n";
return 1;
}

struct can_frame frame {}; // Classical can frame
int32_t numBytes{};
int32_t num_bytes{};

// Connect to zmq
zmq::context_t ctx(1);
zmq::socket_t publisher(ctx, zmq::socket_type::pub);
publisher.bind("ipc:///tmp/speed.ipc");
zmq::context_t context(1);
std::unique_ptr<zmq::socket_t> pub_socket =
std::make_unique<zmq::socket_t>(context, zmq::socket_type::pub);
mq::ZeroMQPublisher publisher{std::move(pub_socket)};
publisher.subscribe("ipc:///tmp/speed.ipc");

catch_signals();
catchSignals();
while (true) {
numBytes = can->readMessage(&frame);
num_bytes = can->receive(&frame);

if (numBytes < 0) {
if (num_bytes < 0) {
if (errno == EINTR) {
std::cout << "interrupt received, exiting gracefully..." << std::endl;
std::cout << "interrupt received, exiting gracefully..." << "\n";
break;
}
if (errno != EAGAIN) {
Expand All @@ -81,19 +86,21 @@ auto main(int argc, char **argv) -> int {

// The len element contains the payload length in bytes and should be used instead of
// can_dlc
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
printf("0x%03X [%d] ", frame.can_id, frame.len);

for (int i = 0; i < frame.len; i++) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
std::cout << printf("%02X ", frame.data[i]);
}

std::cout << "\n";

zmq::message_t msg{static_cast<size_t>(numBytes)};
memcpy(msg.data(), frame.data, static_cast<size_t>(numBytes));
std::vector<uint8_t> message(frame.len);
memcpy(message.data(), frame.data, static_cast<size_t>(num_bytes));

try {
publisher.send(msg, zmq::send_flags::none);
publisher.publish(message);
} catch (zmq::error_t &e) {
std::cout << "interrupt received, proceeding...\n";
}
Expand All @@ -104,11 +111,5 @@ auto main(int argc, char **argv) -> int {
}
}

// Closing ZeroMQ
std::cout << "Closing publisher\n";
publisher.close();
std::cout << "Closing context\n";
ctx.close();

return 0;
}
10 changes: 10 additions & 0 deletions com-middleware/src/mq/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
cc_library(
name = "mq",
srcs = glob(["*.cpp"]),
hdrs = glob(["*.hpp"]),
features = ["warnings_critical_code_gcc"],
visibility = ["//visibility:public"],
deps = [
"@cppzmq",
],
)
28 changes: 28 additions & 0 deletions com-middleware/src/mq/IMQPublisher.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef MQ_PUBLISHER_HPP
#define MQ_PUBLISHER_HPP

#include <cstdint>
#include <string>
#include <vector>

namespace mq {

class IMQPublisher {
protected:
// Constructors
IMQPublisher() = default;
IMQPublisher(const IMQPublisher&) = default;
IMQPublisher(IMQPublisher&&) = default;

// Asignment operators
auto operator=(const IMQPublisher&) -> IMQPublisher& = default;
auto operator=(IMQPublisher&&) -> IMQPublisher& = default;

public:
virtual ~IMQPublisher() = default;
virtual void subscribe(const std::string& topic) = 0;
virtual auto publish(const std::vector<uint8_t>& data) -> bool = 0;
};
} // namespace mq

#endif
27 changes: 27 additions & 0 deletions com-middleware/src/mq/IMQSubscriber.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef MQ_SUBSCRIBER_HPP
#define MQ_SUBSCRIBER_HPP

#include <string>
#include <vector>

namespace mq {

class IMQSubscriber {
protected:
// Constructors
IMQSubscriber() = default;
IMQSubscriber(const IMQSubscriber&) = default;
IMQSubscriber(IMQSubscriber&&) = default;

// Asignment operators
auto operator=(const IMQSubscriber&) -> IMQSubscriber& = default;
auto operator=(IMQSubscriber&&) -> IMQSubscriber& = default;

public:
virtual ~IMQSubscriber() = 0;
virtual void subscribe(const std::string& topic) = 0;
virtual auto receive() -> std::vector<uint8_t> = 0;
};
} // namespace mq

#endif
29 changes: 29 additions & 0 deletions com-middleware/src/mq/ZeroMQPublisher.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include "ZeroMQPublisher.hpp"

#include <iostream>

namespace mq {
ZeroMQPublisher::ZeroMQPublisher(std::unique_ptr<zmq::socket_t> socket)
: m_socket(std::move(socket)) {};

ZeroMQPublisher::~ZeroMQPublisher() {
if (m_socket) {
std::cout << "Closing publisher\n";
m_socket->close();
}
}

void ZeroMQPublisher::subscribe(const std::string& topic) { m_socket->bind(topic); }

auto ZeroMQPublisher::publish(const std::vector<uint8_t>& data) -> bool {
zmq::message_t msg(data.size());
memcpy(msg.data(), data.data(), data.size());
std::cout << m_socket.get() << "\n";
zmq::send_result_t res = m_socket->send(msg, zmq::send_flags::none);
if (res.has_value()) {
std::cout << "!sent\n";
return true;
}
return false;
}
} // namespace mq
Loading

0 comments on commit 9e12a64

Please sign in to comment.