From bdba0234b24823a96800080b98b1ab96743308ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 25 Jan 2015 19:39:15 +0000 Subject: [PATCH] Parse received datagrams. --- CMakeLists.txt | 2 ++ main.cpp | 22 +++++++++-------- socket.cpp | 67 ++++++++++++++++++++++++++++++++++++++++---------- socket.h | 18 +++++++++++--- 4 files changed, 82 insertions(+), 27 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a41e0e2..9d6bcda 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 2.8) project(s20) +add_definitions(-std=gnu++11) + find_package(Qt5 REQUIRED Core Network) add_executable(s20 main.cpp socket.cpp) target_link_libraries(s20 Qt5::Core Qt5::Network) diff --git a/main.cpp b/main.cpp index 97d4e2e..9661413 100644 --- a/main.cpp +++ b/main.cpp @@ -37,24 +37,26 @@ int main(int argc, char *argv[]) std::vector sockets; readDiscoverDatagrams(udpSocketGet, sockets); + delete udpSocketGet; listSockets(sockets); char command; unsigned int number = 1; bool cont=true; - while(cont) + while (cont) { std::cout << "s - pick another socket (default is 1)\nt - toggle power state\nq - quit" << std::endl; std::cin >> command; - switch(command) + switch (command) { - case 'q': - cont = false; - break; - case 's': - std::cin >> number; - case 't': - sockets[number-1].toggle(); + case 'q': + cont = false; + break; + case 's': + std::cin >> number; + case 't': + sockets[number-1].toggle(); + listSockets(sockets); } } return 0; @@ -64,6 +66,6 @@ void listSockets(std::vector const &sockets) { for (std::vector::const_iterator i = sockets.begin() ; i != sockets.end(); ++i) { - std::cout << "IP Address: " << i->ip.toString().toStdString() << "\t MAC Address: " << i->mac.toHex().toStdString() << "\t Powered: " << i->powered << std::endl; + std::cout << "IP Address: " << i->ip.toString().toStdString() << "\t MAC Address: " << i->mac.toHex().toStdString() << "\t Power: " << (i->powered ? "On" : "Off") << std::endl; } } diff --git a/socket.cpp b/socket.cpp index b4fce55..6262391 100644 --- a/socket.cpp +++ b/socket.cpp @@ -18,6 +18,7 @@ #include "socket.h" #include +#include #include Socket::Socket(QHostAddress IPaddress, QByteArray reply) @@ -26,28 +27,68 @@ Socket::Socket(QHostAddress IPaddress, QByteArray reply) mac = reply.mid(7, 6); rmac = mac; std::reverse(rmac.begin(), rmac.end()); - powered = reply.right(1) == QByteArray::fromHex("01"); - QByteArray twenties = QByteArray::fromHex("20 20 20 20 20 20"); - QByteArray zeros = QByteArray::fromHex("00 00 00 00"); - datagram[Subscribe] = QByteArray::fromHex("68 64 00 1e 63 6c") + mac + twenties + rmac + twenties; - datagram[PowerOn] = QByteArray::fromHex("68 64 00 17 64 63") + mac + twenties + zeros + QByteArray::fromHex("01"); - datagram[PowerOff] = QByteArray::fromHex("68 64 00 17 64 63") + mac + twenties + zeros + QByteArray::fromHex("00"); + powered = reply.right(1) == one; + + commandID[Subscribe] = QByteArray::fromHex("63 6c"); + commandID[PowerOn] = QByteArray::fromHex("73 66"); + commandID[PowerOff] = commandID[PowerOn]; + commandID[TableData] = QByteArray::fromHex("72 74"); + + // 2 hex bytes are the total length of the message + datagram[Subscribe] = magicKey + QByteArray::fromHex("00 1e") + commandID[Subscribe] + mac + twenties + rmac + twenties; + datagram[PowerOn] = magicKey + QByteArray::fromHex("00 17 64 63") + mac + twenties + zeros + one; + 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 + one + zeros + zero; } bool Socket::toggle() { - sendDatagram(datagram[Subscribe]); // TODO: process replies - QThread::msleep(100); // wait a little to make toggle reliable - sendDatagram(datagram[powered ? PowerOff : PowerOn]); - powered = !powered; + bool powerOld = powered; + while (powerOld == powered) + { + sendDatagram(Subscribe); + sendDatagram(powerOld ? PowerOff : PowerOn); + } } -void Socket::sendDatagram(QByteArray datagram) +void Socket::sendDatagram(Datagram d) { + udpSocketGet = new QUdpSocket(); + udpSocketGet->bind(QHostAddress::Any, 10000); + udpSocketSend = new QUdpSocket(); udpSocketSend->connectToHost(ip, 10000); - udpSocketSend->write(datagram); - udpSocketSend->disconnectFromHost(); + udpSocketSend->write(datagram[d]); delete udpSocketSend; + readDatagrams(udpSocketGet, d); + delete udpSocketGet; +} + +void Socket::readDatagrams(QUdpSocket *udpSocketGet, Datagram d) +{ + while (udpSocketGet->waitForReadyRead(300)) // 300ms + { + while (udpSocketGet->hasPendingDatagrams()) + { + QByteArray datagramGet; + datagramGet.resize(udpSocketGet->pendingDatagramSize()); + QHostAddress sender; + quint16 senderPort; + + udpSocketGet->readDatagram(datagramGet.data(), datagramGet.size(), &sender, &senderPort); + + if (datagramGet.left(2) == magicKey && datagramGet.mid(4,2) == commandID[d]) + { + std::cout << datagramGet.toHex().toStdString() << std::endl; + switch (d) + { + case Subscribe: + case PowerOff: + case PowerOn: + powered = datagramGet.right(1) == one; + } + } + } + } } diff --git a/socket.h b/socket.h index 1122547..1464e3a 100644 --- a/socket.h +++ b/socket.h @@ -30,10 +30,20 @@ public: bool powered; private: - void sendDatagram(QByteArray datagram); + enum Datagram {Subscribe, PowerOff, PowerOn, TableData, MaxCommands}; - enum {Subscribe, PowerOff, PowerOn}; - QByteArray datagram[3]; + void sendDatagram(Datagram); + void readDatagrams(QUdpSocket *udpSocketGet, Datagram d); + + QByteArray commandID[MaxCommands]; + QByteArray datagram[MaxCommands]; QByteArray rmac; // Reveresed mac - QUdpSocket *udpSocketSend; + + const QByteArray magicKey = QByteArray::fromHex("68 64"); // recognize datagrams from the socket + const QByteArray twenties = QByteArray::fromHex("20 20 20 20 20 20"); // mac address padding + const QByteArray zeros = QByteArray::fromHex("00 00 00 00"); + const QByteArray zero = QByteArray::fromHex("00"); + const QByteArray one = QByteArray::fromHex("01"); + + QUdpSocket *udpSocketSend, *udpSocketGet; };