Orvibo S20 socket manager
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

server.cpp 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*************************************************************************
  2. * Copyright (C) 2015 by Andrius Štikonas <andrius@stikonas.eu> *
  3. * *
  4. * This program is free software; you can redistribute it and/or modify *
  5. * it under the terms of the GNU General Public License as published by *
  6. * the Free Software Foundation; either version 3 of the License, or *
  7. * (at your option) any later version. *
  8. * *
  9. * This program is distributed in the hope that it will be useful, *
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  12. * GNU General Public License for more details. *
  13. * *
  14. * You should have received a copy of the GNU General Public License *
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.*
  16. *************************************************************************/
  17. #include <QNetworkConfiguration>
  18. #include <QNetworkConfigurationManager>
  19. #include <QNetworkSession>
  20. #include <QTimer>
  21. #include <QUdpSocket>
  22. #include "consolereader.h"
  23. #include "server.h"
  24. Server::Server(std::vector<Socket*> *sockets_vector)
  25. {
  26. sockets = sockets_vector;
  27. udpSocketGet = new QUdpSocket(this);
  28. udpSocketGet->bind(QHostAddress::Any, 10000);
  29. connect(udpSocketGet, &QUdpSocket::readyRead, this, &Server::readPendingDatagrams);
  30. discoverSockets();
  31. QTimer *discoverTimer = new QTimer(this);
  32. discoverTimer->setInterval(1 * 60 * 1000); // 1 min
  33. discoverTimer->setSingleShot(false);
  34. connect(discoverTimer, &QTimer::timeout, this, &Server::discoverSockets);
  35. discoverTimer->start();
  36. start();
  37. }
  38. Server::Server(uint16_t port, QByteArray ssid, QByteArray password)
  39. {
  40. QNetworkConfiguration *cfgInitial = new QNetworkConfiguration;
  41. const QNetworkConfiguration *cfg = new QNetworkConfiguration;
  42. QNetworkConfigurationManager *ncm = new QNetworkConfigurationManager;
  43. ncm->updateConfigurations();
  44. *cfgInitial = ncm->defaultConfiguration();
  45. if (ssid == "c") {
  46. ssid = cfgInitial->name().toLocal8Bit();
  47. qDebug() << "SSID unspecified, using current network: " << ssid;
  48. }
  49. bool stop = false;
  50. while (!stop) {
  51. QThread::sleep(1);
  52. const auto nc = ncm->allConfigurations();
  53. for (const auto &x : nc) {
  54. if (x.bearerType() == QNetworkConfiguration::BearerWLAN) {
  55. if (x.name() == "WiWo-S20") {
  56. qDebug() << "Connecting to WiWo-S20 wireless";
  57. cfg = &x;
  58. stop = true;
  59. }
  60. }
  61. }
  62. }
  63. QNetworkSession *session = new QNetworkSession(*cfg, this);
  64. session->open();
  65. qDebug() << "Wait for connected!";
  66. if (session->waitForOpened())
  67. qDebug() << "Connected!";
  68. QUdpSocket *udpSocketSend = new QUdpSocket();
  69. udpSocketGet = new QUdpSocket();
  70. udpSocketGet->bind(QHostAddress::Any, port);
  71. QByteArray reply;
  72. qDebug() << "Send: HF-A11ASSISTHREAD";
  73. udpSocketGet->writeDatagram(QByteArray::fromStdString("HF-A11ASSISTHREAD"), QHostAddress::Broadcast, port);
  74. reply = listen(QByteArray::fromStdString("HF-A11ASSISTHREAD"));
  75. QList<QByteArray> list = reply.split(',');
  76. QHostAddress ip(QString::fromLatin1(list[0]));
  77. qDebug() << "IP: " << ip.toString();
  78. qDebug() << "Send: +ok";
  79. udpSocketGet->writeDatagram(QByteArray::fromStdString("+ok"), ip, port);
  80. qDebug() << "Send: AT+WSSSID=" + QString::fromLatin1(ssid) + "\r";
  81. udpSocketGet->writeDatagram(QByteArray::fromStdString("AT+WSSSID=") + ssid + QByteArray::fromStdString("\r"), ip, port);
  82. listen();
  83. qDebug() << "Send: AT+WSKEY=WPA2PSK,AES," + QString::fromLatin1(password) + "\r";
  84. udpSocketGet->writeDatagram(QByteArray::fromStdString("AT+WSKEY=WPA2PSK,AES,") + password + QByteArray::fromStdString("\r"), ip, port); // FIXME: support different security settings
  85. // OPEN, SHARED, WPAPSK......NONE, WEP, TKIP, AES
  86. listen();
  87. qDebug() << "Send: AT+WMODE=STA\\r";
  88. udpSocketGet->writeDatagram(QByteArray::fromStdString("AT+WMODE=STA\r"), ip, port);
  89. listen();
  90. qDebug() << "Send: AT+Z\\r";
  91. udpSocketGet->writeDatagram(QByteArray::fromStdString("AT+Z\r"), ip, port); // reboot
  92. listen();
  93. session->close();
  94. // FIXME: discover the new socket
  95. qWarning() << "Finished";
  96. session = new QNetworkSession(*cfgInitial, this);
  97. session->open();
  98. if (session->waitForOpened())
  99. qWarning() << "Connected";
  100. discoverSockets();
  101. }
  102. QByteArray Server::listen(QByteArray message)
  103. {
  104. QByteArray reply;
  105. QHostAddress sender;
  106. quint16 senderPort;
  107. bool stop = false;
  108. while (!stop) {
  109. QThread::msleep(50);
  110. while (udpSocketGet->hasPendingDatagrams()) {
  111. reply.resize(udpSocketGet->pendingDatagramSize());
  112. udpSocketGet->readDatagram(reply.data(), reply.size(), &sender, &senderPort);
  113. qDebug() << "Reply: " << QString::fromLatin1(reply.data());
  114. if (reply != message) {
  115. stop = true;
  116. }
  117. }
  118. }
  119. return reply;
  120. }
  121. void Server::run()
  122. {
  123. readPendingDatagrams();
  124. }
  125. void Server::readPendingDatagrams()
  126. {
  127. while (udpSocketGet->hasPendingDatagrams()) {
  128. QByteArray reply, mac;
  129. reply.resize(udpSocketGet->pendingDatagramSize());
  130. QHostAddress sender;
  131. quint16 senderPort;
  132. udpSocketGet->readDatagram(reply.data(), reply.size(), &sender, &senderPort);
  133. if (reply != discover && reply.left(2) == magicKey) { // check for Magic Key
  134. if (reply.mid(4, 2) == QStringLiteral("qa").toLatin1() || reply.mid(4, 2) == QStringLiteral("qg").toLatin1()) { // Reply to discover packet
  135. bool duplicate = false;
  136. for (const auto &socket : *sockets) {
  137. if (socket->ip == sender) {
  138. duplicate = true;
  139. break;
  140. }
  141. }
  142. if (!duplicate) {
  143. Socket *socket = new Socket(sender, reply);
  144. sockets->push_back(socket);
  145. std::sort(sockets->begin(), sockets->end(), [](const Socket* a, const Socket* b) -> bool { return QString::compare(QString(a->mac), QString(b->mac)) < 0 ? true : false; }); // socket name is not known yet
  146. Q_EMIT discovered();
  147. }
  148. mac = reply.mid(7, 6);
  149. } else {
  150. mac = reply.mid(6, 6);
  151. }
  152. for (const auto &socket : *sockets) {
  153. if (socket->mac == mac) {
  154. socket->parseReply(reply);
  155. break;
  156. }
  157. }
  158. }
  159. }
  160. }
  161. void Server::discoverSockets()
  162. {
  163. QUdpSocket *udpSocketSend = new QUdpSocket(this);
  164. udpSocketSend->connectToHost(QHostAddress::Broadcast, 10000);
  165. udpSocketSend->write(discover);
  166. udpSocketSend->write(discover);
  167. udpSocketSend->disconnectFromHost();
  168. delete udpSocketSend;
  169. }
  170. void broadcastPassword(QString password)
  171. {
  172. QUdpSocket *udpSocket = new QUdpSocket();
  173. udpSocket->connectToHost(QHostAddress::Broadcast, 49999);
  174. uint sleep = 15;
  175. for (uint j = 0; j < 4; ++j) { // FIXME: stopping loop on discovery
  176. qWarning() << j;
  177. for (unsigned short int i = 0; i < 200; ++i) {
  178. udpSocket->write(fives(76));
  179. QThread::msleep(sleep);
  180. }
  181. for (unsigned short int i = 0; i < 3; ++i) {
  182. udpSocket->write(fives(89));
  183. QThread::msleep(sleep);
  184. }
  185. QChar *data = password.data();
  186. while (!data->isNull()) {
  187. udpSocket->write(fives(data->unicode() + 76));
  188. QThread::msleep(sleep);
  189. ++data;
  190. }
  191. for (unsigned short int i = 0; i < 3; ++i) {
  192. udpSocket->write(fives(86));
  193. QThread::msleep(sleep);
  194. }
  195. for (unsigned short int i = 0; i < 3; ++i) {
  196. udpSocket->write(fives(332 + password.length()));
  197. QThread::msleep(sleep);
  198. }
  199. }
  200. udpSocket->disconnectFromHost();
  201. delete udpSocket;
  202. // FIXME: special slightly modified SocketData packet might is needed here
  203. }
  204. QByteArray fives(unsigned short int length)
  205. {
  206. QByteArray packet;
  207. packet.fill(0x05, length);
  208. return packet;
  209. }