2015-01-14 00:50:55 +00:00
/*************************************************************************
* 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
2015-01-31 15:28:34 +00:00
Socket : : Socket ( QHostAddress IPaddress , QByteArray reply )
2015-01-14 00:50:55 +00:00
{
ip = IPaddress ;
2015-01-31 15:28:34 +00:00
mac = reply . mid ( 7 , 6 ) ;
2015-01-14 13:55:28 +00:00
rmac = mac ;
2015-01-31 15:28:34 +00:00
std : : reverse ( rmac . begin ( ) , rmac . end ( ) ) ;
2015-01-14 13:55:28 +00:00
2015-01-31 15:28:34 +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
2015-01-31 15:28:34 +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 ] ;
2015-01-31 15:28:34 +00:00
commandID [ TableData ] = QByteArray : : fromHex ( " 72 74 " ) ;
2015-01-26 00:55:20 +00:00
commandID [ SocketData ] = commandID [ TableData ] ;
commandID [ TimingData ] = commandID [ TableData ] ;
2015-01-31 15:28:34 +00:00
commandID [ WriteSocketData ] = QByteArray : : fromHex ( " 74 6d " ) ;
2015-01-25 19:39:15 +00:00
// 2 hex bytes are the total length of the message
2015-01-31 15:28:34 +00:00
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 ;
2015-01-31 15:28:34 +00:00
while ( powerOld = = powered )
2015-01-25 19:39:15 +00:00
{
2015-01-31 15:28:34 +00:00
sendDatagram ( Subscribe ) ;
sendDatagram ( powerOld ? PowerOff : PowerOn ) ;
2015-01-25 19:39:15 +00:00
}
2015-01-14 13:55:28 +00:00
}
2015-01-31 15:28:34 +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 ( )
{
2015-01-31 15:28:34 +00:00
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
}
2015-01-31 15:28:34 +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 ( ) ;
2015-01-31 15:28:34 +00:00
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 ( ) ;
2015-01-31 15:28:34 +00:00
udpSocketSend - > connectToHost ( ip , 10000 ) ;
udpSocketSend - > write ( datagram [ d ] ) ;
2015-01-14 13:55:28 +00:00
delete udpSocketSend ;
2015-01-31 15:28:34 +00:00
readDatagrams ( udpSocketGet ) ;
2015-01-25 19:39:15 +00:00
delete udpSocketGet ;
}
2015-01-31 15:28:34 +00:00
// 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
{
2015-01-31 15:28:34 +00:00
while ( udpSocketGet - > waitForReadyRead ( 300 ) ) // 300ms
2015-01-25 19:39:15 +00:00
{
2015-01-31 15:28:34 +00:00
while ( udpSocketGet - > hasPendingDatagrams ( ) )
2015-01-25 19:39:15 +00:00
{
2015-01-31 15:28:34 +00:00
QByteArray reply ;
reply . resize ( udpSocketGet - > pendingDatagramSize ( ) ) ;
2015-01-25 19:39:15 +00:00
QHostAddress sender ;
quint16 senderPort ;
2015-01-31 15:28:34 +00:00
udpSocketGet - > readDatagram ( reply . data ( ) , reply . size ( ) , & sender , & senderPort ) ;
parseReply ( reply ) ;
}
}
}
2015-01-25 19:39:15 +00:00
2015-01-31 15:28:34 +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
}
}
2015-01-31 15:28:34 +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
}
2015-01-31 15:28:34 +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 ) ;
}