s20/socket.cpp

162 lines
6.8 KiB
C++
Raw Normal View History

/*************************************************************************
* Copyright (C) 2015 by Andrius Štikonas <andrius@stikonas.eu> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#include "socket.h"
2015-01-14 13:55:28 +00:00
#include <algorithm>
2015-01-25 19:39:15 +00:00
#include <iostream>
2015-01-14 13:55:28 +00:00
Socket::Socket ( QHostAddress IPaddress, QByteArray reply )
{
ip = IPaddress;
mac = reply.mid ( 7, 6 );
2015-01-14 13:55:28 +00:00
rmac = mac;
std::reverse ( rmac.begin(), rmac.end() );
2015-01-14 13:55:28 +00:00
powered = reply.right ( 1 ) == one;
// 68:64:00:06:71:61 initial detection ??
// 68:64:00:1e:63:6c:ac:cf:23:35:f5:8c:20:20:20:20:20:20:38:38:38:38:38:38:20:20:20:20:20:20 // to 42.121.111.208
2015-01-25 19:39:15 +00:00
commandID[Subscribe] = QByteArray::fromHex ( "63 6c" );
commandID[PowerOn] = QByteArray::fromHex ( "73 66" );
2015-01-25 19:39:15 +00:00
commandID[PowerOff] = commandID[PowerOn];
commandID[TableData] = QByteArray::fromHex ( "72 74" );
2015-01-26 00:55:20 +00:00
commandID[SocketData] = commandID[TableData];
commandID[TimingData] = commandID[TableData];
commandID[WriteSocketData] = QByteArray::fromHex ( "74 6d" );
2015-01-25 19:39:15 +00:00
// 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 + QByteArray::fromHex ( "01 00 00" ) + zeros;
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" );
2015-01-14 13:55:28 +00:00
}
2015-01-26 00:55:20 +00:00
void Socket::toggle()
2015-01-14 13:55:28 +00:00
{
2015-01-25 19:39:15 +00:00
bool powerOld = powered;
while ( powerOld == powered )
2015-01-25 19:39:15 +00:00
{
sendDatagram ( Subscribe );
sendDatagram ( powerOld ? PowerOff : PowerOn );
2015-01-25 19:39:15 +00:00
}
2015-01-14 13:55:28 +00:00
}
void Socket::changeSocketName ( /*QString name*/ )
{
sendDatagram ( Subscribe );
std::cout << datagram[WriteSocketData].toHex().toStdString();
sendDatagram ( WriteSocketData );
}
2015-01-26 00:55:20 +00:00
void Socket::tableData()
{
sendDatagram ( Subscribe );
sendDatagram ( TableData );
datagram[SocketData] = magicKey + QByteArray::fromHex ( "00 1d" ) + commandID[SocketData] + mac + twenties + zeros + QByteArray::fromHex ( "04 00 00" ) + zeros;
datagram[TimingData] = magicKey + QByteArray::fromHex ( "00 1d" ) + commandID[TimingData] + mac + twenties + zeros + QByteArray::fromHex ( "03 00 00" ) + zeros;
// table number + 00 + version number
sendDatagram ( SocketData );
sendDatagram ( TimingData );
2015-01-26 00:55:20 +00:00
}
void Socket::sendDatagram ( Datagram d )
2015-01-14 13:55:28 +00:00
{
2015-01-25 19:39:15 +00:00
udpSocketGet = new QUdpSocket();
udpSocketGet->bind ( QHostAddress::Any, 10000, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
2015-01-25 19:39:15 +00:00
2015-01-14 13:55:28 +00:00
udpSocketSend = new QUdpSocket();
udpSocketSend->connectToHost ( ip, 10000 );
udpSocketSend->write ( datagram[d] );
2015-01-14 13:55:28 +00:00
delete udpSocketSend;
readDatagrams ( udpSocketGet);
2015-01-25 19:39:15 +00:00
delete udpSocketGet;
}
// FIXME: try to always listen for incoming datagrams to make everything asyncronous
void Socket::readDatagrams ( QUdpSocket *udpSocketGet)
2015-01-25 19:39:15 +00:00
{
while ( udpSocketGet->waitForReadyRead ( 300 ) ) // 300ms
2015-01-25 19:39:15 +00:00
{
while ( udpSocketGet->hasPendingDatagrams() )
2015-01-25 19:39:15 +00:00
{
QByteArray reply;
reply.resize ( udpSocketGet->pendingDatagramSize() );
2015-01-25 19:39:15 +00:00
QHostAddress sender;
quint16 senderPort;
udpSocketGet->readDatagram ( reply.data(), reply.size(), &sender, &senderPort );
parseReply ( reply );
}
}
}
2015-01-25 19:39:15 +00:00
bool Socket::parseReply ( QByteArray reply )
{
if ( reply.left ( 2 ) != magicKey )
return false;
QByteArray id = reply.mid ( 4, 2 );
unsigned int datagram = std::distance ( commandID, std::find ( commandID, commandID + MaxCommands, id ) ); // match commandID with enum
if ( datagram == 3 ) // determine the table number
{
unsigned int table = reply[reply.indexOf ( zeros ) + 4]; // Table number immediately follows zeros
switch ( table )
{
case 1:
datagram = TableData;
break;
case 3:
datagram = TimingData;
break;
case 4:
datagram = SocketData;
break;
default:
return false;
2015-01-25 19:39:15 +00:00
}
}
std::cout << reply.toHex().toStdString() << " " << datagram << std::endl; // for debugging purposes only
switch ( datagram )
{
case Subscribe:
case PowerOff:
case PowerOn:
powered = reply.right ( 1 ) == one;
break;
case TableData:
// FIXME: order might be swapped;
socketTableVersion = reply.mid ( reply.indexOf ( QByteArray::fromHex ( "000100000600" ) ) + 6, 2 );
// 000100000600
break;
case SocketData:
remotePassword = reply.mid ( reply.indexOf ( rmac + twenties ) + 12, 12 );
name = reply.mid ( reply.indexOf ( rmac + twenties ) + 24, 16 );
break;
case TimingData:
break;
default:
return false;
}
return true;
2015-01-14 13:55:28 +00:00
}
QByteArray Socket::fromIP(unsigned char a, unsigned char b, unsigned char c, unsigned char d)
{
return QByteArray::number(a) + QByteArray::number(b) + QByteArray::number(c) + QByteArray::number(d);
}