From daf7213a0525244b73d4fc8ceb56ec5790ccd70f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Tue, 3 Feb 2015 01:24:47 +0000 Subject: [PATCH] Move network and input handling to separate threads. Add some debugging output. --- consolereader.cpp | 30 +++++++++++++++++++++--------- consolereader.h | 4 +++- main.cpp | 9 +-------- server.cpp | 14 ++++++++++++-- server.h | 7 ++++++- socket.cpp | 43 ++++++++++++++++++++++++++++--------------- socket.h | 10 ++++++---- 7 files changed, 77 insertions(+), 40 deletions(-) diff --git a/consolereader.cpp b/consolereader.cpp index 064300d..a00db88 100644 --- a/consolereader.cpp +++ b/consolereader.cpp @@ -25,28 +25,40 @@ ConsoleReader::ConsoleReader ( std::vector *sockets_vector ) start(); } +ConsoleReader::~ConsoleReader() +{ + delete discoveryTimer; +} + void ConsoleReader::run() { - char command; + QThread::sleep(1); // wait until sockets are discovered + for ( unsigned i = 0; i < sockets->size(); ++i ) + { + connect((*sockets)[i], &Socket::stateChanged, this, &ConsoleReader::listSockets); + } + listSockets(); + + std::string command; unsigned int number = 0; bool cont = true; while ( cont ) { std::cin >> command; - switch ( command ) + switch ( command[0] ) { case 'd': - ( *sockets ) [number]->tableData(); + (*sockets) [number]->tableData(); break; case 'n': -// std::cout << "Enter new name (max 16 characters)" << std::endl; -// string name; -// std::cin >> name; - ( *sockets ) [number]->changeSocketName(); + { + command.erase(0,1); + (*sockets) [number]->changeSocketName(QString::fromStdString(command)); break; + } case 'p': - ( *sockets ) [number]->toggle(); + (*sockets) [number]->toggle(); break; case 'q': cont = false; @@ -72,5 +84,5 @@ void ConsoleReader::listSockets() std::cout << "Socket Name: " << (*i)->name.toStdString() << "\t Remote Password: " << (*i)->remotePassword.toStdString() << std::endl; } std::cout << "___________________________________________________________________________\n" << std::endl; - std::cout << "d - update table data\nn - change socket name\ns - pick another socket (default is 1)\np - toggle power state\nq - quit" << std::endl; + std::cout << "d - update table data\nnName - change socket name to Name (max 16 characters)\ns - pick another socket (default is 1)\np - toggle power state\nq - quit" << std::endl; } diff --git a/consolereader.h b/consolereader.h index 886949c..38aca85 100644 --- a/consolereader.h +++ b/consolereader.h @@ -27,11 +27,13 @@ class ConsoleReader : public QThread { public: ConsoleReader ( std::vector *sockets_vector ); - void run (); + ~ConsoleReader(); + void run(); void listSockets(); private: std::vector *sockets; + QTimer *discoveryTimer; }; #endif /* CONSOLEREADER_H */ diff --git a/main.cpp b/main.cpp index 00feffb..9306133 100644 --- a/main.cpp +++ b/main.cpp @@ -15,7 +15,6 @@ * along with this program. If not, see .* *************************************************************************/ -#include #include #include "consolereader.h" @@ -28,13 +27,7 @@ int main(int argc, char *argv[]) std::vector *sockets = new std::vector; Server server(sockets); ConsoleReader *reader = new ConsoleReader(sockets); - QThread::sleep(2); - server.readPendingDatagrams(); - - for ( unsigned i = 0; i < sockets->size(); ++i ) - { - QObject::connect((*sockets)[i], &Socket::stateChanged, reader, &ConsoleReader::listSockets); - } + qWarning() << "event loop"; return app.exec(); } diff --git a/server.cpp b/server.cpp index d826932..0e03c96 100644 --- a/server.cpp +++ b/server.cpp @@ -15,7 +15,7 @@ * along with this program. If not, see .* *************************************************************************/ -#include +#include #include "consolereader.h" #include "server.h" @@ -33,7 +33,9 @@ Server::Server ( std::vector *sockets_vector ) udpSocketSend->disconnectFromHost(); delete udpSocketSend; - connect ( udpSocketGet, &QUdpSocket::readyRead, this, &Server::readPendingDatagrams ); + connect ( udpSocketGet, &QUdpSocket::readyRead, this, &Server::readPendingDatagrams); + qWarning() << "starting server"; + start(); } Server::~Server() @@ -41,8 +43,14 @@ Server::~Server() delete udpSocketGet; } +void Server::run() +{ + readPendingDatagrams(); +} + void Server::readPendingDatagrams() { +// qWarning () << "reading datagam"; while ( udpSocketGet->hasPendingDatagrams() ) { QByteArray reply; @@ -67,12 +75,14 @@ void Server::readPendingDatagrams() } if ( !duplicate ) { + qWarning() << "Socket found"; Socket *socket = new Socket ( sender, reply ); sockets->push_back ( socket ); } } else { +// qWarning() << "preparing to parse datagram"; QByteArray mac = reply.mid(6,6); for ( std::vector::iterator i = sockets->begin() ; i != sockets->end(); ++i ) { diff --git a/server.h b/server.h index f4556f4..65895dd 100644 --- a/server.h +++ b/server.h @@ -18,9 +18,13 @@ #ifndef SERVER_H #define SERVER_H +#include + #include "socket.h" -class Server : public QObject +class QUdpSocket; + +class Server : public QThread { public: Server ( std::vector *sockets_vector ); @@ -28,6 +32,7 @@ public: void discoverSockets (); void readPendingDatagrams(); + void run(); private: QByteArray discover = QByteArray::fromHex ( "68 64 00 06 71 61" ); diff --git a/socket.cpp b/socket.cpp index 858514a..4420bfd 100644 --- a/socket.cpp +++ b/socket.cpp @@ -19,6 +19,8 @@ #include #include +#include +#include Socket::Socket ( QHostAddress IPaddress, QByteArray reply ) { @@ -45,38 +47,39 @@ Socket::Socket ( QHostAddress IPaddress, QByteArray reply ) datagram[PowerOff] = magicKey + QByteArray::fromHex ( "00 17 64 63" ) + mac + twenties + zeros + zero; datagram[TableData] = magicKey + QByteArray::fromHex ( "00 1d" ) + commandID[TableData] + mac + twenties + zeros + QByteArray::fromHex ( "01 00 00" ) + zeros; - tableData(); - - datagram[WriteSocketData] = magicKey + QByteArray::fromHex ( "00 a5" ) + commandID[WriteSocketData] + mac + twenties + zeros + QByteArray::fromHex ( "04:00:01" ) /*table number and unknown*/ + QByteArray::fromHex ( "8a:00" ) /* record length = 138 bytes*/ + QByteArray::fromHex ( ":01:00:43:25" ) + mac + twenties + rmac + twenties + QByteArray::fromHex ( "38:38:38:38:38:38:20:20:20:20:20:20" ) + QByteArray ( "Heater " ) + QByteArray::fromHex ( "04:00:20:00:00:00:14:00:00:00:05:00:00:00:10:27" ) + fromIP ( 42,121,111,208 ) + QByteArray::fromHex ( "10:27" ) + "vicenter.orvibo.com" + " " + twenties + twenties + twenties + fromIP ( 192,168,1,212 ) + QByteArray::fromHex ( "c0:a8:01:01:ff:ff:ff:00:01:01:00:08:00:ff:00:00" ); + udpSocket = new QUdpSocket(); + udpSocket->connectToHost ( ip, 10000 ); + subscribed = false; subscribeTimer = new QTimer(this); - subscribeTimer->setInterval(2*60*1000); + subscribeTimer->setInterval(200); // increase later, debug + subscribeTimer->setSingleShot(false); connect(subscribeTimer, &QTimer::timeout, this, &Socket::subscribe); subscribeTimer->start(); - subscribe(); } Socket::~Socket() { delete subscribeTimer; + delete udpSocket; } void Socket::subscribe() { + qWarning() << "subscribing"; sendDatagram ( Subscribe ); } void Socket::toggle() { - bool powerOld = powered; - while ( powerOld == powered ) - { - sendDatagram ( powerOld ? PowerOff : PowerOn ); - } + sendDatagram ( powered ? PowerOff : PowerOn ); } -void Socket::changeSocketName ( /*QString name*/ ) +void Socket::changeSocketName ( QString newName ) { + QByteArray name = newName.toLatin1().leftJustified(16, ' ', true); + + datagram[WriteSocketData] = magicKey + QByteArray::fromHex ( "00 a5" ) + commandID[WriteSocketData] + mac + twenties + zeros + QByteArray::fromHex ( "04:00:01" ) /*table number and unknown*/ + QByteArray::fromHex ( "8a:00" ) /* record length = 138 bytes*/ + QByteArray::fromHex ( "01:00" ) /* record number = 1*/ + versionID + mac + twenties + rmac + twenties + remotePassword + name + QByteArray::fromHex ( "04:00:20:00:00:00:14:00:00:00:05:00:00:00:10:27" ) + fromIP ( 42,121,111,208 ) + QByteArray::fromHex ( "10:27" ) + "vicenter.orvibo.com" + " " + twenties + twenties + twenties + fromIP ( 192,168,1,212 ) + QByteArray::fromHex ( "c0:a8:01:01:ff:ff:ff:00:01:01:00:08:00:ff:00:00" ); sendDatagram ( WriteSocketData ); } @@ -92,14 +95,13 @@ void Socket::tableData() void Socket::sendDatagram ( Datagram d ) { - udpSocket = new QUdpSocket(); - udpSocket->connectToHost ( ip, 10000 ); + qWarning() << "sending datagram" << d << " subscribed = " << subscribed; udpSocket->write ( datagram[d] ); - delete udpSocket; } bool Socket::parseReply ( QByteArray reply ) { + qWarning() << "parsing datagram"; if ( reply.left ( 2 ) != magicKey ) { return false; @@ -114,12 +116,15 @@ bool Socket::parseReply ( QByteArray reply ) { case 1: datagram = TableData; + qWarning() << "got Table"; break; case 3: datagram = TimingData; + qWarning() << "got Timing"; break; case 4: datagram = SocketData; + qWarning() << "got Socket"; break; default: return false; @@ -129,6 +134,9 @@ bool Socket::parseReply ( QByteArray reply ) switch ( datagram ) { case Subscribe: + subscribed = true; + subscribeTimer->setInterval(2*60*1000); // 2min + qWarning() << "got Subscribe"; case PowerOff: case PowerOn: { @@ -139,19 +147,24 @@ bool Socket::parseReply ( QByteArray reply ) break; } case TableData: +// qWarning() << "got TableData"; // FIXME: order might be swapped; socketTableVersion = reply.mid ( reply.indexOf ( QByteArray::fromHex ( "000100000600" ) ) + 6, 2 ); // 000100000600 break; case SocketData: +// qWarning() << "got SocketData"; remotePassword = reply.mid ( reply.indexOf ( rmac + twenties ) + 12, 12 ); name = reply.mid ( reply.indexOf ( rmac + twenties ) + 24, 16 ); + versionID = reply.mid ( reply.indexOf ( rmac + twenties ) - 14, 2 ); Q_EMIT stateChanged(); break; case TimingData: +// qWarning() << "got TimingData"; break; case WriteSocketData: - Q_EMIT stateChanged(); + sendDatagram ( SocketData ); +// Q_EMIT stateChanged(); break; default: return false; diff --git a/socket.h b/socket.h index b1f2173..00a9c1a 100644 --- a/socket.h +++ b/socket.h @@ -21,7 +21,8 @@ #include #include #include -#include + +class QUdpSocket; const QByteArray magicKey = QByteArray::fromHex ( "68 64" ); // recognize datagrams from the socket @@ -37,13 +38,13 @@ public: ~Socket(); void toggle(); void tableData(); - void changeSocketName ( /*QString name*/ ); + void changeSocketName ( QString newName ); bool parseReply ( QByteArray ); QHostAddress ip, localIP; QByteArray mac; bool powered; - QString name, remotePassword; + QByteArray name, remotePassword; private: enum Datagram {Subscribe, PowerOff, PowerOn, TableData, SocketData, TimingData, WriteSocketData, MaxCommands}; @@ -55,6 +56,7 @@ private: QByteArray commandID[MaxCommands]; QByteArray datagram[MaxCommands]; QByteArray rmac; // Reveresed mac + QByteArray versionID; QByteArray socketTableNumber, socketTableVersion, timingTableNumber, timingTableVersion; const QByteArray twenties = QByteArray::fromHex ( "20 20 20 20 20 20" ); // mac address padding @@ -63,8 +65,8 @@ private: const QByteArray one = QByteArray::fromHex ( "01" ); QUdpSocket *udpSocket; - QTimer *subscribeTimer; + bool subscribed; };