diff --git a/DbSerialServer.pro b/DbSerialServer.pro new file mode 100644 index 0000000..e930b8a --- /dev/null +++ b/DbSerialServer.pro @@ -0,0 +1,28 @@ +QT += core network serialport +QT -= gui widgets + +DBLIBS += + +TARGET = serialserver + +PROJECT_ROOT = .. + +SOURCES += main.cpp \ + master.cpp \ + slave.cpp + +HEADERS += \ + master.h \ + slave.h + +FORMS += + +RESOURCES += + +TRANSLATIONS += + +configinstall.path = $${OUT_PWD}/$${PROJECT_ROOT}/bin +configinstall.files += serialserver.ini +INSTALLS += configinstall + +include($${PROJECT_ROOT}/app.pri) diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..dc2a2cd --- /dev/null +++ b/main.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +#include "master.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + QCoreApplication::setApplicationName("serialserver"); + QCoreApplication::setOrganizationDomain("brunner.ninja"); + QCoreApplication::setOrganizationName("0xFEEDC0DE64"); + + const auto configPath = QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(QCoreApplication::applicationName() + QStringLiteral(".ini")); + QSettings settings(configPath, QSettings::IniFormat); + + qDebug() << "Opening serialport..."; + auto serialPort = new QSerialPort; + serialPort->setPortName(settings.value("serial/port").toString()); + serialPort->setBaudRate(settings.value("serial/baudrate").toInt()); + if(!serialPort->open(QIODevice::ReadWrite)) + { + qWarning() << serialPort->errorString(); + qFatal("could not open serialport"); + return -1; + } + + qDebug() << "Starting tcp server..."; + auto server = new QTcpServer; + + { + auto listenAddress = settings.value("server/address", "Any").toString(); + QHostAddress hostAddress; + + if(listenAddress == "Null") + hostAddress = QHostAddress::Null; + else if(listenAddress == "Broadcast") + hostAddress = QHostAddress::Broadcast; + else if(listenAddress == "LocalHost") + hostAddress = QHostAddress::LocalHost; + else if(listenAddress == "LocalHostIPv6") + hostAddress = QHostAddress::LocalHostIPv6; + else if(listenAddress == "Any") + hostAddress = QHostAddress::Any; + else if(listenAddress == "AnyIPv6") + hostAddress = QHostAddress::AnyIPv6; + else if(listenAddress == "AnyIPv4") + hostAddress = QHostAddress::AnyIPv4; + else + hostAddress = QHostAddress(listenAddress); + + if(!server->listen(hostAddress, (quint16)settings.value("server/port", 1234).toUInt())) + { + qWarning() << server->errorString(); + qFatal("could not start listening"); + return -2; + } + } + + new Master(serialPort, server, &app); + + return app.exec(); +} diff --git a/master.cpp b/master.cpp new file mode 100644 index 0000000..8199bd9 --- /dev/null +++ b/master.cpp @@ -0,0 +1,53 @@ +#include "master.h" + +#include +#include +#include + +#include "slave.h" + +Master::Master(QSerialPort *serialPort, QTcpServer *server, QObject *parent) : + QObject(parent), + m_serialPort(serialPort), + m_server(server) +{ + m_serialPort->setParent(this); + connect(m_serialPort, &QIODevice::readyRead, this, &Master::readyRead); + connect(m_serialPort, &QSerialPort::errorOccurred, this, &Master::errorOccurred); + + m_server->setParent(this); + connect(m_server, SIGNAL(newConnection()), this, SLOT(newConnection())); + + qDebug() << "startup successfull!"; +} + +void Master::writeData(const QByteArray &byteArray) +{ + m_serialPort->write(byteArray); +} + +void Master::readyRead() +{ + Q_EMIT dataReady(m_serialPort->readAll()); +} + +void Master::errorOccurred(QSerialPort::SerialPortError error) +{ + if(error == QSerialPort::NoError) //actually occured! qt is dumb + return; + + qWarning() << error << enumToKey(error); + qFatal("error occured in serial port"); + qApp->quit(); +} + +void Master::newConnection() +{ + auto socket = m_server->nextPendingConnection(); + if(socket) + { + auto slave = new Slave(socket, this); + connect(slave, &Slave::dataReady, this, &Master::writeData); + connect(this, &Master::dataReady, slave, &Slave::writeData); + } +} diff --git a/master.h b/master.h new file mode 100644 index 0000000..8d6ab8c --- /dev/null +++ b/master.h @@ -0,0 +1,46 @@ +#ifndef MASTER_H +#define MASTER_H + +#include +#include +#include + +class QTcpServer; + +class Master : public QObject +{ + Q_OBJECT + +public: + explicit Master(QSerialPort *serialPort, QTcpServer *server, QObject *parent = 0); + +Q_SIGNALS: + void dataReady(const QByteArray &byteArray); + +public Q_SLOTS: + void writeData(const QByteArray &byteArray); + +private Q_SLOTS: + void readyRead(); + void errorOccurred(QSerialPort::SerialPortError error); + void newConnection(); + +private: + template static const char *enumToKey(T value) + { + Q_STATIC_ASSERT_X(QtPrivate::IsQEnumHelper::Value, "QMetaEnum::fromType only works with enums declared as Q_ENUM or Q_FLAG"); + + const QMetaObject *metaObject = qt_getEnumMetaObject(T()); + const char *nameOfEnum = qt_getEnumName(T()); + int index = metaObject->indexOfEnumerator(nameOfEnum); + if(index == -1) + return "!!ENUM_NOT_FOUND!!"; + auto metaEnum = metaObject->enumerator(index); + return metaEnum.valueToKey((int)value); + } + + QSerialPort *m_serialPort; + QTcpServer *m_server; +}; + +#endif // MASTER_H diff --git a/serialserver.ini b/serialserver.ini new file mode 100644 index 0000000..d455868 --- /dev/null +++ b/serialserver.ini @@ -0,0 +1,7 @@ +[serial] +port = COM3 +baudrate = 9600 + +[server] +address = Any +port = 1234 diff --git a/slave.cpp b/slave.cpp new file mode 100644 index 0000000..d8f195c --- /dev/null +++ b/slave.cpp @@ -0,0 +1,32 @@ +#include "slave.h" + +#include +#include + +Slave::Slave(QTcpSocket *socket, QObject *parent) : + QObject(parent), + m_socket(socket) +{ + m_socket->setParent(this); + + qDebug() << this << "connected from" << m_socket->peerAddress(); + + connect(m_socket, &QIODevice::readyRead, this, &Slave::readyRead); + connect(m_socket, SIGNAL(disconnected()), this, SLOT(disconnected())); + connect(m_socket, SIGNAL(disconnected()), this, SLOT(deleteLater())); +} + +void Slave::writeData(const QByteArray &byteArray) +{ + m_socket->write(byteArray); +} + +void Slave::readyRead() +{ + Q_EMIT dataReady(m_socket->readAll()); +} + +void Slave::disconnected() +{ + qDebug() << this << "disconnected!"; +} diff --git a/slave.h b/slave.h new file mode 100644 index 0000000..7f23178 --- /dev/null +++ b/slave.h @@ -0,0 +1,28 @@ +#ifndef SLAVE_H +#define SLAVE_H + +#include + +class QTcpSocket; + +class Slave : public QObject +{ + Q_OBJECT +public: + explicit Slave(QTcpSocket *socket, QObject *parent = 0); + +Q_SIGNALS: + void dataReady(const QByteArray &byteArray); + +public Q_SLOTS: + void writeData(const QByteArray &byteArray); + +private Q_SLOTS: + void readyRead(); + void disconnected(); + +private: + QTcpSocket *m_socket; +}; + +#endif // SLAVE_H