diff options
| author | Thomas Vanbesien <tvanbesi@proton.me> | 2026-03-11 11:02:24 +0100 |
|---|---|---|
| committer | Thomas Vanbesien <tvanbesi@proton.me> | 2026-03-11 11:09:40 +0100 |
| commit | 35309337aacac2eac7d7215e526bddcf7647b8cf (patch) | |
| tree | 3626e5e5e17e23122deab1bf3ade0502872873f3 /src | |
| download | QtXpl2-35309337aacac2eac7d7215e526bddcf7647b8cf.tar.gz QtXpl2-35309337aacac2eac7d7215e526bddcf7647b8cf.zip | |
Initial project setup: Qt 6.10.2 TCP client library for Alchemie XPL2 protocol
- Static library (src/) with QML singleton Xpl2Client for TCP communication
- Qt Quick demo app (demo/) with connection UI, command input, and response log
Diffstat (limited to 'src')
| -rw-r--r-- | src/CMakeLists.txt | 17 | ||||
| -rw-r--r-- | src/Xpl2Client.cpp | 86 | ||||
| -rw-r--r-- | src/Xpl2Client.h | 53 |
3 files changed, 156 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..3339013 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,17 @@ +qt_add_library(QtXpl2 STATIC) + +qt_add_qml_module( + QtXpl2 + URI + Xpl2 + VERSION + 1.0 + SOURCES + Xpl2Client.h + Xpl2Client.cpp + OUTPUT_DIRECTORY + "${PROJECT_BINARY_DIR}/qml/Xpl2") + +target_compile_features(QtXpl2 PRIVATE cxx_std_17) + +target_link_libraries(QtXpl2 PRIVATE Qt6::Core Qt6::Network Qt6::Quick) diff --git a/src/Xpl2Client.cpp b/src/Xpl2Client.cpp new file mode 100644 index 0000000..db53792 --- /dev/null +++ b/src/Xpl2Client.cpp @@ -0,0 +1,86 @@ +/** + * @file Xpl2Client.cpp + * @brief TCP client for the Alchemie XPL2 printhead protocol. + */ +#include "Xpl2Client.h" + +Xpl2Client::Xpl2Client(QObject *parent) : QObject(parent) { + connect(&m_socket, &QTcpSocket::connected, this, &Xpl2Client::onConnected); + connect(&m_socket, &QTcpSocket::disconnected, this, + &Xpl2Client::onDisconnected); + connect(&m_socket, &QTcpSocket::readyRead, this, &Xpl2Client::onReadyRead); + connect(&m_socket, &QAbstractSocket::errorOccurred, this, + &Xpl2Client::onErrorOccurred); +} + +QString Xpl2Client::host() const { return m_host; } + +void Xpl2Client::setHost(const QString &host) { + if (m_host == host) + return; + m_host = host; + emit hostChanged(); +} + +quint16 Xpl2Client::port() const { return m_port; } + +void Xpl2Client::setPort(quint16 port) { + if (m_port == port) + return; + m_port = port; + emit portChanged(); +} + +bool Xpl2Client::isConnected() const { + return m_socket.state() == QAbstractSocket::ConnectedState; +} + +void Xpl2Client::connectToServer() { + if (isConnected()) { + emit statusMessage(QStringLiteral("Already connected")); + return; + } + emit statusMessage( + QStringLiteral("Connecting to %1:%2…").arg(m_host).arg(m_port)); + m_socket.connectToHost(m_host, m_port); +} + +void Xpl2Client::disconnectFromServer() { + if (!isConnected()) + return; + m_socket.disconnectFromHost(); +} + +void Xpl2Client::sendCommand(const QString &command) { + if (!isConnected()) { + emit errorOccurred(QStringLiteral("Not connected")); + return; + } + QByteArray data = command.toUtf8() + '\n'; + m_socket.write(data); + emit statusMessage(QStringLiteral("Sent: %1").arg(command)); +} + +void Xpl2Client::onConnected() { + emit connectedChanged(); + emit statusMessage(QStringLiteral("Connected to %1:%2") + .arg(m_socket.peerName()) + .arg(m_socket.peerPort())); +} + +void Xpl2Client::onDisconnected() { + emit connectedChanged(); + emit statusMessage(QStringLiteral("Disconnected")); +} + +void Xpl2Client::onReadyRead() { + while (m_socket.canReadLine()) { + QString line = QString::fromUtf8(m_socket.readLine()).trimmed(); + emit responseReceived(line); + } +} + +void Xpl2Client::onErrorOccurred(QAbstractSocket::SocketError error) { + Q_UNUSED(error) + emit errorOccurred(m_socket.errorString()); +} diff --git a/src/Xpl2Client.h b/src/Xpl2Client.h new file mode 100644 index 0000000..f052962 --- /dev/null +++ b/src/Xpl2Client.h @@ -0,0 +1,53 @@ +/** + * @file Xpl2Client.h + * @brief TCP client for the Alchemie XPL2 printhead protocol. + */ +#pragma once + +#include <QObject> +#include <QQmlEngine> +#include <QTcpSocket> + +class Xpl2Client : public QObject { + Q_OBJECT + QML_ELEMENT + QML_SINGLETON + + Q_PROPERTY(QString host READ host WRITE setHost NOTIFY hostChanged) + Q_PROPERTY(quint16 port READ port WRITE setPort NOTIFY portChanged) + Q_PROPERTY(bool connected READ isConnected NOTIFY connectedChanged) + +public: + explicit Xpl2Client(QObject *parent = nullptr); + + QString host() const; + void setHost(const QString &host); + + quint16 port() const; + void setPort(quint16 port); + + bool isConnected() const; + + Q_INVOKABLE void connectToServer(); + Q_INVOKABLE void disconnectFromServer(); + Q_INVOKABLE void sendCommand(const QString &command); + +signals: + void hostChanged(); + void portChanged(); + void connectedChanged(); + void responseReceived(const QString &response); + void errorOccurred(const QString &error); + void statusMessage(const QString &message); + +private slots: + void onConnected(); + void onDisconnected(); + void onReadyRead(); + void onErrorOccurred(QAbstractSocket::SocketError error); + +private: + QTcpSocket m_socket; + QString m_host = QStringLiteral("127.0.0.1"); + quint16 m_port = 5000; +}; |
