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-03-08 11:29:33 +00:00
2015-09-07 15:43:08 +01:00
# include <QDataStream>
2015-03-08 11:29:33 +00:00
# include <QMutex>
2015-02-03 01:24:47 +00:00
# include <QThread>
# include <QUdpSocket>
2015-01-14 13:55:28 +00:00
2015-08-18 15:29:09 +01:00
Socket : : Socket ( QHostAddress IPaddress , QByteArray reply )
2015-01-14 00:50:55 +00:00
{
ip = IPaddress ;
2015-08-18 15:29:09 +01:00
mac = reply . mid ( 7 , 6 ) ;
2015-01-14 13:55:28 +00:00
rmac = mac ;
2015-08-18 15:29:09 +01:00
std : : reverse ( rmac . begin ( ) , rmac . end ( ) ) ;
powered = reply . right ( 1 ) = = one ;
2015-01-25 19:39:15 +00:00
2015-08-18 15:29:09 +01:00
commandID [ QueryAll ] = QStringLiteral ( " qa " ) . toLatin1 ( ) ;
commandID [ Discover ] = QStringLiteral ( " qg " ) . toLatin1 ( ) ; // qg
2016-03-14 00:35:40 +00:00
commandID [ Subscribe ] = QStringLiteral ( " cl " ) . toLatin1 ( ) ; // Claim
2015-08-18 15:29:09 +01:00
commandID [ PowerOn ] = QStringLiteral ( " sf " ) . toLatin1 ( ) ; // State Flip (change of power state)
2015-01-25 19:39:15 +00:00
commandID [ PowerOff ] = commandID [ PowerOn ] ;
2015-08-18 15:29:09 +01:00
commandID [ ReadTable ] = QStringLiteral ( " rt " ) . toLatin1 ( ) ;
2015-05-27 00:03:33 +01:00
commandID [ SocketData ] = commandID [ ReadTable ] ;
commandID [ TimingData ] = commandID [ ReadTable ] ;
2015-08-18 15:29:09 +01:00
commandID [ TableModify ] = QStringLiteral ( " tm " ) . toLatin1 ( ) ;
QByteArray commandIDPower = QStringLiteral ( " dc " ) . toLatin1 ( ) ; // Socket change responce
2015-01-25 19:39:15 +00:00
// 2 hex bytes are the total length of the message
2015-04-02 22:10:06 +01:00
datagram [ Discover ] = commandID [ Discover ] + mac + twenties ;
2015-02-15 15:11:39 +00:00
datagram [ Subscribe ] = commandID [ Subscribe ] + mac + twenties + rmac + twenties ;
2015-02-21 21:14:22 +00:00
datagram [ PowerOn ] = commandIDPower + mac + twenties + zeros + one ;
datagram [ PowerOff ] = commandIDPower + mac + twenties + zeros + zero ;
2016-03-14 00:35:40 +00:00
datagram [ ReadTable ] = commandID [ ReadTable ] + mac + twenties + /*zeros*/ QByteArray : : fromHex ( " 00 00 00 00 " ) /*cookie*/ + QByteArray : : fromHex ( " 01 00 " ) + zero + zeros ;
2015-01-31 15:28:34 +00:00
2016-09-02 20:56:06 +01:00
udpSocket = new QUdpSocket ( this ) ;
2015-08-18 15:29:09 +01:00
udpSocket - > connectToHost ( ip , 10000 ) ;
2015-02-01 01:42:45 +00:00
2015-08-18 15:29:09 +01:00
connect ( this , & Socket : : datagramQueued , this , & Socket : : processQueue ) ;
2015-02-01 01:42:45 +00:00
subscribeTimer = new QTimer ( this ) ;
2015-08-18 15:29:09 +01:00
subscribeTimer - > setInterval ( 2 * 60 * 1000 ) ; // 2 min
2015-02-03 01:24:47 +00:00
subscribeTimer - > setSingleShot ( false ) ;
2015-02-01 01:42:45 +00:00
connect ( subscribeTimer , & QTimer : : timeout , this , & Socket : : subscribe ) ;
subscribeTimer - > start ( ) ;
2015-02-07 17:29:12 +00:00
subscribe ( ) ;
tableData ( ) ;
2015-02-01 01:42:45 +00:00
}
2015-08-18 15:29:09 +01:00
void Socket : : sendDatagram ( Datagram d )
2015-02-07 17:29:12 +00:00
{
commands . enqueue ( d ) ;
Q_EMIT datagramQueued ( ) ;
}
void Socket : : run ( )
{
2015-03-08 11:29:33 +00:00
QMutex mutex ;
2015-08-18 15:29:09 +01:00
if ( ! mutex . tryLock ( ) ) {
2015-03-08 11:29:33 +00:00
return ;
2015-03-11 12:34:56 +00:00
}
2015-03-08 11:29:33 +00:00
2015-03-02 12:21:10 +00:00
unsigned short retryCount = 0 ;
QByteArray currentDatagram , previousDatagram = 0 , recordLength ;
2015-08-18 15:29:09 +01:00
while ( commands . size ( ) > 0 ) {
2015-03-02 12:21:10 +00:00
currentDatagram = datagram [ commands . head ( ) ] ;
2015-08-18 15:29:09 +01:00
if ( previousDatagram = = currentDatagram ) {
2015-03-02 12:21:10 +00:00
+ + retryCount ;
2015-03-11 12:34:56 +00:00
}
2015-08-18 15:29:09 +01:00
if ( retryCount = = 5 ) {
2015-03-02 12:21:10 +00:00
std : : cout < < " Stop retrying: " < < currentDatagram . toHex ( ) . toStdString ( ) < < std : : endl ;
commands . dequeue ( ) ;
2015-03-08 11:29:33 +00:00
retryCount = 0 ;
2015-03-02 12:21:10 +00:00
}
2015-11-01 03:56:05 +00:00
2015-02-15 15:11:39 +00:00
uint16_t length = currentDatagram . length ( ) + 4 ; // +4 for magicKey and total message length
2015-11-01 03:56:05 +00:00
recordLength = intToHex ( length , 2 , false ) ;
2015-02-15 15:11:39 +00:00
2015-08-18 15:29:09 +01:00
udpSocket - > write ( magicKey + recordLength + currentDatagram ) ;
2015-03-08 11:29:33 +00:00
previousDatagram = currentDatagram ;
2015-02-07 17:29:12 +00:00
QThread : : msleep ( 100 ) ;
}
2015-03-08 11:29:33 +00:00
mutex . unlock ( ) ;
2015-02-07 17:29:12 +00:00
}
2015-02-01 01:42:45 +00:00
void Socket : : subscribe ( )
{
2015-08-18 15:29:09 +01:00
sendDatagram ( Subscribe ) ;
2015-01-14 13:55:28 +00:00
}
2015-04-02 22:10:06 +01:00
void Socket : : discover ( )
{
2015-08-18 15:29:09 +01:00
sendDatagram ( Discover ) ;
2015-04-02 22:10:06 +01:00
}
2015-01-26 00:55:20 +00:00
void Socket : : toggle ( )
2015-01-14 13:55:28 +00:00
{
2015-08-18 15:29:09 +01:00
sendDatagram ( powered ? PowerOff : PowerOn ) ;
2015-01-14 13:55:28 +00:00
}
2015-05-26 00:02:19 +01:00
void Socket : : powerOff ( )
{
if ( powered )
2015-08-18 15:29:09 +01:00
sendDatagram ( PowerOff ) ;
2015-05-26 00:02:19 +01:00
Q_EMIT stateChanged ( ) ;
}
void Socket : : powerOn ( )
{
if ( ! powered )
2015-08-18 15:29:09 +01:00
sendDatagram ( PowerOn ) ;
2015-05-26 00:02:19 +01:00
Q_EMIT stateChanged ( ) ;
}
2015-08-18 15:29:09 +01:00
void Socket : : changeSocketName ( QString newName )
2015-01-31 15:28:34 +00:00
{
2015-02-03 01:24:47 +00:00
QByteArray name = newName . toLatin1 ( ) . leftJustified ( 16 , ' ' , true ) ;
2015-11-16 01:10:27 +00:00
writeSocketData ( name , remotePassword , timezone , offTime ) ;
2015-02-15 12:31:21 +00:00
}
2015-08-18 15:29:09 +01:00
void Socket : : changeSocketPassword ( QString newPassword )
2015-02-15 12:31:21 +00:00
{
QByteArray password = newPassword . toLatin1 ( ) . leftJustified ( 12 , ' ' , true ) ;
2015-11-16 01:10:27 +00:00
writeSocketData ( socketName , password , timezone , offTime ) ;
2015-02-15 12:31:21 +00:00
}
2015-02-03 01:24:47 +00:00
2015-08-18 15:29:09 +01:00
void Socket : : changeTimezone ( int8_t newTimezone )
2015-02-15 12:31:21 +00:00
{
2015-11-16 01:10:27 +00:00
writeSocketData ( socketName , remotePassword , newTimezone , offTime ) ;
2015-02-15 12:31:21 +00:00
}
2015-11-16 01:10:27 +00:00
void Socket : : setOffTimer ( uint16_t offTime )
2015-02-15 12:31:21 +00:00
{
2015-11-16 01:10:27 +00:00
writeSocketData ( socketName , remotePassword , timezone , offTime ) ;
2015-08-18 14:25:32 +01:00
}
2015-11-16 01:10:27 +00:00
void Socket : : toggleOffTimer ( )
2015-09-04 22:49:13 +01:00
{
2015-11-16 01:10:27 +00:00
offTimerEnabled = ! offTimerEnabled ;
writeSocketData ( socketName , remotePassword , timezone , offTime ) ;
2015-09-04 22:49:13 +01:00
}
2015-11-16 01:10:27 +00:00
void Socket : : writeSocketData ( QByteArray socketName , QByteArray remotePassword , int8_t timezone , uint16_t offTime )
2015-08-18 14:25:32 +01:00
{
Rename dhcpMode to DST_TimezoneOffset.
Describtion by Fernando Silva:
While most TZs are integer, there are half time zones: Venezuela/Caracas, for
example, is GMT -4.5 and Kabul GMT +4.5. It is awkward, but we found that these
"half time zones" are identified by the second least significant bit of byte 161
(yes, the same used for DST). Therefore, we have the following possible combinations
for byte 161:
- 00: integer TZ, DST on
- 01: integer TZ, DST off
- 02: half TZ, DST on
- 03: half TZ, DST off
As a reference, one may consider the following examples:
- Azores (GMT-1), DST on: byte 161 = 00, byte 164 = FF
- Caracas (GMT-4.5), DST off: byte 161 = 03, byte 164 = FC
- Paris (GMT+1), DST off: byte 161 = 01, byte 164 = 01
- Kabul (GMT+4.5), DST on: bute 161 = 02, byte 164 = 04
2016-04-12 12:36:57 +01:00
QByteArray record = QByteArray : : fromHex ( " 01:00 " ) /* record number = 1*/ + versionID + mac + twenties + rmac + twenties + remotePassword + socketName + icon + hardwareVersion + firmwareVersion + wifiFirmwareVersion + port + staticServerIP + port + domainServerName + localIP + localGatewayIP + localNetMask + DST_TimezoneOffset + discoverable + timeZoneSet + intToHex ( timezone , 1 ) + ( offTimerEnabled ? QByteArray : : fromHex ( " 01:00 " ) : QByteArray : : fromHex ( " 00:ff " ) ) + intToHex ( offTime , 2 ) + zeros + zeros + zeros + QStringLiteral ( " 000000000000000000000000000000 " ) . toLocal8Bit ( ) ;
2015-02-15 15:11:39 +00:00
2015-11-01 03:56:05 +00:00
QByteArray recordLength = intToHex ( record . length ( ) , 2 ) ; // 2 bytes
2015-02-12 23:26:31 +00:00
2015-08-18 15:29:09 +01:00
datagram [ TableModify ] = commandID [ TableModify ] + mac + twenties + zeros + QByteArray : : fromHex ( " 04:00:01 " ) /*table number and unknown*/ + recordLength + record ;
sendDatagram ( TableModify ) ;
2015-01-31 15:28:34 +00:00
}
2015-01-26 00:55:20 +00:00
void Socket : : tableData ( )
{
2015-08-18 15:29:09 +01:00
sendDatagram ( ReadTable ) ;
datagram [ SocketData ] = commandID [ SocketData ] + mac + twenties + zeros + QByteArray : : fromHex ( " 04 00 00 " ) + zeros ;
datagram [ TimingData ] = commandID [ TimingData ] + mac + twenties + zeros + QByteArray : : fromHex ( " 03 00 00 " ) + zeros ;
2015-01-31 15:28:34 +00:00
// table number + 00 + version number
2015-08-18 15:29:09 +01:00
sendDatagram ( SocketData ) ;
sendDatagram ( TimingData ) ;
2015-01-26 00:55:20 +00:00
}
2015-08-18 15:29:09 +01:00
bool Socket : : parseReply ( QByteArray reply )
2015-01-31 15:28:34 +00:00
{
2015-08-18 15:29:09 +01:00
if ( reply . left ( 2 ) ! = magicKey ) {
2015-01-31 15:28:34 +00:00
return false ;
2015-02-01 01:42:45 +00:00
}
2015-01-31 15:28:34 +00:00
2015-08-18 15:29:09 +01:00
QByteArray id = reply . mid ( 4 , 2 ) ;
unsigned int datagram = std : : distance ( commandID , std : : find ( commandID , commandID + MaxCommands , id ) ) ; // match commandID with enum
if ( datagram = = ReadTable ) { // determine the table number
unsigned int table = reply [ reply . indexOf ( twenties ) + 11 ] ;
switch ( table ) {
2015-01-31 15:28:34 +00:00
case 1 :
break ;
case 3 :
datagram = TimingData ;
Rename dhcpMode to DST_TimezoneOffset.
Describtion by Fernando Silva:
While most TZs are integer, there are half time zones: Venezuela/Caracas, for
example, is GMT -4.5 and Kabul GMT +4.5. It is awkward, but we found that these
"half time zones" are identified by the second least significant bit of byte 161
(yes, the same used for DST). Therefore, we have the following possible combinations
for byte 161:
- 00: integer TZ, DST on
- 01: integer TZ, DST off
- 02: half TZ, DST on
- 03: half TZ, DST off
As a reference, one may consider the following examples:
- Azores (GMT-1), DST on: byte 161 = 00, byte 164 = FF
- Caracas (GMT-4.5), DST off: byte 161 = 03, byte 164 = FC
- Paris (GMT+1), DST off: byte 161 = 01, byte 164 = 01
- Kabul (GMT+4.5), DST on: bute 161 = 02, byte 164 = 04
2016-04-12 12:36:57 +01:00
// qDebug() << reply.toHex();
2015-01-31 15:28:34 +00:00
break ;
case 4 :
datagram = SocketData ;
break ;
2015-03-11 12:34:56 +00:00
case 0 :
qWarning ( ) < < " No table " ; // FIXME: initial data query
2015-01-31 15:28:34 +00:00
default :
2015-03-11 12:34:56 +00:00
qWarning ( ) < < " Failed to identify data table. " ;
2015-05-27 00:03:33 +01:00
datagram = ReadTable ;
2015-01-31 15:28:34 +00:00
return false ;
2015-01-25 19:39:15 +00:00
}
}
2015-08-18 15:29:09 +01:00
switch ( datagram ) {
2015-05-27 00:03:33 +01:00
case QueryAll :
2015-08-18 15:29:09 +01:00
case Discover : {
2015-11-01 15:40:48 +00:00
uint32_t time = hexToInt ( reply . right ( 5 ) . left ( 4 ) ) ;
2015-04-02 22:10:06 +01:00
socketDateTime . setDate ( QDate ( 1900 , 01 , 01 ) ) ; // midnight 1900-01-01
socketDateTime . setTime ( QTime ( 0 , 0 , 0 ) ) ;
socketDateTime = socketDateTime . addSecs ( time ) ;
}
2015-01-31 15:28:34 +00:00
case Subscribe :
case PowerOff :
2015-08-18 15:29:09 +01:00
case PowerOn : {
2015-02-01 01:42:45 +00:00
bool poweredOld = powered ;
2015-03-08 11:34:01 +00:00
powered = reply . right ( 1 ) = = one ;
2015-08-18 15:29:09 +01:00
if ( powered ! = poweredOld ) {
2015-02-01 01:42:45 +00:00
Q_EMIT stateChanged ( ) ;
2015-03-11 12:34:56 +00:00
}
2015-08-18 15:29:09 +01:00
if ( datagram = = PowerOff & & powered = = true ) { // Required to deque
2015-02-07 17:29:12 +00:00
datagram = PowerOn ;
}
2015-01-31 15:28:34 +00:00
break ;
2015-02-01 01:42:45 +00:00
}
2015-05-27 00:03:33 +01:00
case ReadTable :
2015-01-31 15:28:34 +00:00
// FIXME: order might be swapped;
2015-08-18 15:29:09 +01:00
socketTableVersion = reply . mid ( reply . indexOf ( QByteArray : : fromHex ( " 000100000600 " ) ) + 6 , 2 ) ;
2015-01-31 15:28:34 +00:00
// 000100000600
break ;
2015-08-18 15:29:09 +01:00
case SocketData : {
2015-03-08 11:29:33 +00:00
// std::cout << reply.toHex().toStdString() << " " << datagram << std::endl; // for debugging purposes only
2015-08-18 15:29:09 +01:00
unsigned short int index = reply . indexOf ( rmac + twenties ) ;
versionID = reply . mid ( index - 14 , 2 ) ;
2015-02-09 21:09:50 +00:00
index + = 12 ; // length of rmac + padding
2015-08-18 15:29:09 +01:00
remotePassword = reply . mid ( index , 12 ) ; // max 12 symbols
2015-02-09 21:09:50 +00:00
index + = 12 ;
2015-08-18 15:29:09 +01:00
socketName = reply . mid ( index , 16 ) ; // max 16 symbols
2015-02-09 21:09:50 +00:00
index + = 16 ;
2015-08-18 15:29:09 +01:00
icon = reply . mid ( index , 2 ) ;
2015-02-09 21:09:50 +00:00
index + = 2 ;
2015-08-18 15:29:09 +01:00
hardwareVersion = reply . mid ( index , 4 ) ;
2015-02-09 21:09:50 +00:00
index + = 4 ;
2015-08-18 15:29:09 +01:00
firmwareVersion = reply . mid ( index , 4 ) ;
2015-02-09 21:09:50 +00:00
index + = 4 ;
2015-08-18 15:29:09 +01:00
wifiFirmwareVersion = reply . mid ( index , 4 ) ;
2015-02-11 00:33:04 +00:00
index + = 6 ;
2015-08-18 15:29:09 +01:00
staticServerIP = reply . mid ( index , 4 ) ; // 42.121.111.208 is used
2015-02-15 15:26:37 +00:00
index + = 6 ;
2015-08-18 15:29:09 +01:00
domainServerName = reply . mid ( index , 40 ) ;
2015-02-15 15:26:37 +00:00
index + = 40 ;
2015-08-18 15:29:09 +01:00
localIP = reply . mid ( index , 4 ) ;
2015-02-11 00:33:04 +00:00
index + = 4 ;
2015-08-18 15:29:09 +01:00
localGatewayIP = reply . mid ( index , 4 ) ;
2015-02-11 14:31:20 +00:00
index + = 4 ;
2015-08-18 15:29:09 +01:00
localNetMask = reply . mid ( index , 4 ) ;
2015-02-11 14:31:20 +00:00
index + = 4 ;
Rename dhcpMode to DST_TimezoneOffset.
Describtion by Fernando Silva:
While most TZs are integer, there are half time zones: Venezuela/Caracas, for
example, is GMT -4.5 and Kabul GMT +4.5. It is awkward, but we found that these
"half time zones" are identified by the second least significant bit of byte 161
(yes, the same used for DST). Therefore, we have the following possible combinations
for byte 161:
- 00: integer TZ, DST on
- 01: integer TZ, DST off
- 02: half TZ, DST on
- 03: half TZ, DST off
As a reference, one may consider the following examples:
- Azores (GMT-1), DST on: byte 161 = 00, byte 164 = FF
- Caracas (GMT-4.5), DST off: byte 161 = 03, byte 164 = FC
- Paris (GMT+1), DST off: byte 161 = 01, byte 164 = 01
- Kabul (GMT+4.5), DST on: bute 161 = 02, byte 164 = 04
2016-04-12 12:36:57 +01:00
DST_TimezoneOffset = reply . mid ( index , 1 ) ;
2016-04-17 23:03:36 +01:00
dst = DST_TimezoneOffset = = QByteArray : : fromHex ( " 00 " ) | | DST_TimezoneOffset = = QByteArray : : fromHex ( " 02 " ) ;
2015-02-11 14:31:20 +00:00
+ + index ;
2015-08-18 15:29:09 +01:00
discoverable = reply . mid ( index , 1 ) ;
2015-02-11 14:31:20 +00:00
+ + index ;
2015-08-18 15:29:09 +01:00
timeZoneSet = reply . mid ( index , 1 ) ;
2015-02-11 14:31:20 +00:00
+ + index ;
2015-11-01 22:25:23 +00:00
timezone = hexToInt ( reply . mid ( index , 1 ) ) ;
2016-04-30 13:35:52 +01:00
socketDateTime = socketDateTime . addSecs ( timezone * 3600 ) ;
2015-02-11 14:31:20 +00:00
+ + index ;
2015-11-16 01:10:27 +00:00
offTimerEnabled = reply . mid ( index , 2 ) = = QByteArray : : fromHex ( " 01:00 " ) ;
2015-08-18 14:25:32 +01:00
index + = 2 ;
2015-11-16 01:10:27 +00:00
offTime = hexToInt ( reply . mid ( index , 2 ) ) ;
2015-02-01 01:42:45 +00:00
Q_EMIT stateChanged ( ) ;
2015-01-31 15:28:34 +00:00
break ;
2015-02-09 21:09:50 +00:00
}
2015-01-31 15:28:34 +00:00
case TimingData :
2015-04-02 22:56:57 +01:00
// std::cout << reply.toHex().toStdString() << " " << datagram << std::endl; // for debugging purposes only
2015-01-31 15:28:34 +00:00
break ;
2015-05-27 00:03:33 +01:00
case TableModify :
2015-08-18 15:29:09 +01:00
sendDatagram ( SocketData ) ;
2015-02-01 01:42:45 +00:00
break ;
2015-01-31 15:28:34 +00:00
default :
return false ;
}
2015-02-07 17:29:12 +00:00
2015-08-18 15:29:09 +01:00
if ( commands . size ( ) > 0 ) {
if ( datagram = = commands . head ( ) ) {
2015-02-07 17:29:12 +00:00
commands . dequeue ( ) ;
}
}
2015-01-31 15:28:34 +00:00
return true ;
2015-01-14 13:55:28 +00:00
}
2015-11-01 00:31:38 +00:00
2015-11-01 03:56:05 +00:00
// length in bytes
2015-11-01 15:40:48 +00:00
QByteArray Socket : : intToHex ( unsigned int decimal , unsigned int length , bool littleEndian ) {
2015-11-01 00:31:38 +00:00
QByteArray hex ;
2015-11-01 03:56:05 +00:00
QDataStream stream ( & hex , QIODevice : : WriteOnly ) ;
littleEndian ? stream . setByteOrder ( QDataStream : : LittleEndian ) : stream . setByteOrder ( QDataStream : : BigEndian ) ;
stream < < decimal ;
return littleEndian ? hex . left ( length ) : hex . right ( length ) ;
2015-11-01 00:31:38 +00:00
}
2015-11-01 15:40:48 +00:00
int Socket : : hexToInt ( QByteArray hex , bool littleEndian ) {
QDataStream stream ( & hex , QIODevice : : ReadOnly ) ;
littleEndian ? stream . setByteOrder ( QDataStream : : LittleEndian ) : stream . setByteOrder ( QDataStream : : BigEndian ) ;
switch ( hex . length ( ) ) {
case 1 :
uint8_t value ;
stream > > value ;
return value ;
case 2 :
uint16_t value2 ;
stream > > value2 ;
return value2 ;
case 4 :
uint32_t value4 ;
stream > > value4 ;
return value4 ;
default :
return 0 ;
}
}