mirror of
https://github.com/Sani7/remote-ui.git
synced 2026-10-26 21:51:13 +01:00
server extensions
move gpio and visa extensions to extensions folder
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
Reference in New Issue
Block a user