server extensions

move gpio and visa extensions to extensions folder
This commit is contained in:
2026-02-14 14:32:43 +01:00
parent cf3aa22164
commit 2e1d461026
9 changed files with 14 additions and 74 deletions
+67
View File
@@ -0,0 +1,67 @@
#include "CAN_interface.hpp"
#include "spdlog/spdlog.h"
CAN_Interface::CAN_Interface(QObject *parent) : QObject(parent), m_canDevice(nullptr)
{
if (!QCanBus::instance()->plugins().contains(QStringLiteral("socketcan")))
{
SPDLOG_CRITICAL("Runtime error: CAN Interface: socketcan plugin not found");
throw std::runtime_error("CAN Interface: socketcan plugin not found");
}
}
CAN_Interface::~CAN_Interface()
{
m_canDevice->disconnectDevice();
delete m_canDevice;
}
void CAN_Interface::connect_to_dev(QString dev)
{
QString errorString;
m_canDevice = QCanBus::instance()->createDevice(QStringLiteral("socketcan"), dev, &errorString);
if (!m_canDevice)
{
// Error handling goes here
SPDLOG_CRITICAL("Runtime error: CAN Interface: {}", errorString.toStdString());
throw std::runtime_error("CAN Interface: " + errorString.toStdString());
}
connect(m_canDevice, &QCanBusDevice::errorOccurred, this,
[=, this](QCanBusDevice::CanBusError error) { processErrors(error); });
m_canDevice->connectDevice();
connect(m_canDevice, &QCanBusDevice::framesReceived, this, [this] {
for (QCanBusFrame &frame : m_canDevice->readAllFrames())
{
emit frame_received(frame);
}
});
}
void CAN_Interface::send_frame(const QCanBusFrame frame)
{
if (m_canDevice == nullptr)
{
SPDLOG_CRITICAL("CAN dev = nullptr");
return;
}
m_canDevice->writeFrame(frame);
emit frame_send(frame);
}
void CAN_Interface::processErrors(QCanBusDevice::CanBusError error) const
{
switch (error)
{
case QCanBusDevice::ReadError:
case QCanBusDevice::WriteError:
case QCanBusDevice::ConnectionError:
case QCanBusDevice::ConfigurationError:
case QCanBusDevice::UnknownError:
SPDLOG_CRITICAL("CAN Interface: {} {}", qt_getEnumName(error), m_canDevice->errorString().toStdString());
break;
default:
break;
}
}
+62
View File
@@ -0,0 +1,62 @@
#pragma once
#include <QCanBus>
#include <QCanBusDevice>
#include <QCanBusFrame>
#include <QObject>
/**
* @brief Class representing a CAN interface
*
*/
class CAN_Interface : public QObject
{
Q_OBJECT
public:
/**
* @brief Construct a new CAN Interface object
*
* @param parent The parent QObject
*/
CAN_Interface(QObject *parent = nullptr);
/**
* @brief Destroy the CAN Interface object
*
*/
~CAN_Interface();
/**
* @brief Connect to a CAN device
*
* @param dev The device to connect to (e.g. "can0")
*/
void connect_to_dev(QString dev);
/**
* @brief Send a CAN frame
*
* @param frame The frame to send
*/
void send_frame(const QCanBusFrame frame);
signals:
/**
* @brief Signal emitted when a CAN frame is received
*
* @param frame The received CAN frame
*/
void frame_received(QCanBusFrame frame);
/**
* @brief Signal emitted when a CAN frame is sent
*
* @param frame The sent CAN frame
*/
void frame_send(QCanBusFrame frame);
private:
/**
* @brief Private method to process CAN bus errors
*
* @param error The CAN bus error
*/
void processErrors(QCanBusDevice::CanBusError error) const;
QCanBusDevice *m_canDevice;
};
+84
View File
@@ -0,0 +1,84 @@
#include "gpio.hpp"
#include "spdlog/spdlog.h"
#include <filesystem>
GPIO::GPIO(QObject *parent) : QObject(parent), m_offset(0)
{
}
GPIO::~GPIO()
{
#if defined(__linux__) && (defined(__aarch64__) || defined(__x86_64__))
if (!m_request.get())
return;
m_request->release();
#endif
}
void GPIO::configure_pin(Direction dir, uint8_t gpio)
{
#if defined(__linux__) && (defined(__aarch64__) || defined(__x86_64__))
if (m_request.get() != nullptr)
return;
std::filesystem::path chip_path("/dev/gpiochip0");
m_offset = gpio;
if (dir == Direction::Output)
{
try
{
m_request = std::make_unique<gpiod::line_request>(
::gpiod::chip(chip_path)
.prepare_request()
.set_consumer("unisim_cpp")
.add_line_settings(m_offset,
::gpiod::line_settings().set_direction(::gpiod::line::direction::OUTPUT))
.do_request());
}
catch (...)
{
SPDLOG_CRITICAL("Could not set gpio {} as output, run binary as root", gpio);
}
}
if (dir == Direction::Input)
{
try
{
m_request = std::make_unique<gpiod::line_request>(
::gpiod::chip(chip_path)
.prepare_request()
.set_consumer("unisim_cpp")
.add_line_settings(m_offset,
::gpiod::line_settings().set_direction(::gpiod::line::direction::INPUT))
.do_request());
}
catch (...)
{
SPDLOG_CRITICAL("Could not set gpio {} as input, run binary as root", gpio);
}
}
#else
Q_UNUSED(dir);
Q_UNUSED(gpio);
#endif
}
void GPIO::set_value(bool value)
{
#if defined(__linux__) && (defined(__aarch64__) || defined(__x86_64__))
if (!m_request.get())
return;
m_request->set_value(m_offset, (gpiod::line::value)value);
#else
Q_UNUSED(value);
#endif
}
bool GPIO::value()
{
#if defined(__linux__) && (defined(__aarch64__) || defined(__x86_64__))
if (!m_request.get())
return false;
return (bool)m_request->get_value(m_offset);
#else
return 0;
#endif
}
+63
View File
@@ -0,0 +1,63 @@
#pragma once
#include <QObject>
#if defined(__linux__) && (defined(__aarch64__) || defined(__x86_64__))
#include <gpiod.hpp>
#else
#endif
/**
* @brief Class representing a GPIO pin
*
*/
class GPIO : public QObject
{
Q_OBJECT
public:
/**
* @brief Enum representing pin direction
*
*/
enum Direction
{
Input,
Output
};
/**
* @brief Construct a new GPIO object
*
* @param parent The parent QObject
*/
explicit GPIO(QObject *parent = nullptr);
/**
* @brief Destroy the GPIO object
*
*/
~GPIO();
/**
* @brief Configure a GPIO pin as input or output
*
* @param dir The direction of the pin (Input or Output)
* @param gpio The GPIO pin number
*/
void configure_pin(Direction dir, uint8_t gpio);
/**
* @brief Set the value of the GPIO pin
*
* @param val The value to set (true for high, false for low)
*/
void set_value(bool val);
/**
* @brief Get the value of the GPIO pin
*
* @return bool The value of the pin (true for high, false for low)
*/
bool value();
private:
#if defined(__linux__) && (defined(__aarch64__) || defined(__x86_64__))
std::unique_ptr<gpiod::line_request> m_request;
#endif
unsigned int m_offset;
};
+73
View File
@@ -0,0 +1,73 @@
#include "visa.hpp"
#include <QCoreApplication>
#include <QTcpSocket>
Visa::Visa(QObject *parent)
: QObject(parent), m_tcp_socket(new QTcpSocket(this)), m_connected(false), m_reconnect(false)
{
QObject::connect(m_tcp_socket, &QTcpSocket::connected, this, [=, this] {
m_connected = true;
emit s_connected();
});
QObject::connect(m_tcp_socket, &QTcpSocket::disconnected, this, [=, this] {
m_connected = false;
emit s_disconnected();
if (m_reconnect)
{
connect(m_ip, m_port);
m_reconnect = false;
}
});
QObject::connect(m_tcp_socket, &QTcpSocket::readyRead, this, [=, this] {
emit s_data_ready(QString::fromUtf8(m_tcp_socket->readAll()));
});
}
Visa::~Visa()
{
if (m_connected)
m_tcp_socket->disconnect();
}
void Visa::connect(QString ip, quint16 port)
{
if (m_connected)
{
m_tcp_socket->disconnect();
m_ip = ip;
m_port = port;
m_reconnect = true;
return;
}
m_tcp_socket->connectToHost(ip, port);
}
void Visa::disconnect()
{
m_tcp_socket->disconnect();
}
bool Visa::connected() const
{
return m_connected;
}
void Visa::send(QString data)
{
data.append('\n');
m_tcp_socket->write(data.toUtf8());
m_tcp_socket->waitForBytesWritten();
}
QString Visa::query(QString data)
{
uint32_t counter = 0;
m_data.clear();
send(data);
while (!m_data_ready && counter < 1024)
{
QCoreApplication::processEvents();
counter++;
}
return m_data;
}
+85
View File
@@ -0,0 +1,85 @@
#pragma once
#include <QObject>
Q_FORWARD_DECLARE_OBJC_CLASS(QTcpSocket);
/**
* @brief Class representing a VISA interface also known as SCIPI over TCP/IP
*
*/
class Visa : public QObject
{
Q_OBJECT
public:
/**
* @brief Construct a new Visa object
*
* @param parent The parent QObject
*/
explicit Visa(QObject *parent = nullptr);
/**
* @brief Destroy the Visa object
*
*/
~Visa();
/**
* @brief Connect to a VISA device
*
* @param ip The IP address of the VISA device
* @param port The port number of the VISA device
*/
void connect(QString ip, quint16 port);
/**
* @brief Disconnect from the VISA device
*
*/
void disconnect();
/**
* @brief Check if the VISA device is connected
*
* @return true If the device is connected
* @return false If the device is not connected
*/
bool connected() const;
/**
* @brief Send data to the VISA device
*
* @param data The data to send
*/
void send(QString data);
/**
* @brief Query the VISA device
*
* @param data The query data
* @return QString The response from the device
*/
QString query(QString data);
signals:
/**
* @brief Signal emitted when the device is disconnected
*
*/
void s_disconnected();
/**
* @brief Signal emitted when the device is connected
*
*/
void s_connected();
/**
* @brief Signal emitted when data is ready to be read
*
* @param data The data that is ready to be read
*/
void s_data_ready(QString data);
private:
QTcpSocket *m_tcp_socket;
QString m_ip;
quint16 m_port;
bool m_connected;
bool m_reconnect;
};