2016-05-30 23:58:31 +02:00
// STL includes
# include <cstring>
# include <cstdio>
# include <iostream>
2016-08-08 00:17:00 +02:00
# include <exception>
2016-05-30 23:58:31 +02:00
// Linux includes
# include <fcntl.h>
# include <QStringList>
# include <QUdpSocket>
# include <QHostInfo>
// Local Hyperion includes
2016-08-28 07:12:48 +02:00
# include "ProviderUdp.h"
2016-05-30 23:58:31 +02:00
2020-06-28 23:05:32 +02:00
const ushort MAX_PORT = 65535 ;
2020-11-14 17:58:56 +01:00
ProviderUdp : : ProviderUdp ( const QJsonObject & deviceConfig )
2020-08-08 00:21:19 +02:00
: LedDevice ( deviceConfig )
2020-11-14 17:58:56 +01:00
, _udpSocket ( nullptr )
2020-02-10 15:21:58 +01:00
, _port ( 1 )
, _defaultHost ( " 127.0.0.1 " )
2016-05-30 23:58:31 +02:00
{
2020-11-01 21:56:19 +01:00
_latchTime_ms = 0 ;
2016-05-30 23:58:31 +02:00
}
2016-08-28 07:12:48 +02:00
ProviderUdp : : ~ ProviderUdp ( )
2016-05-30 23:58:31 +02:00
{
2020-08-08 00:21:19 +02:00
delete _udpSocket ;
2016-05-30 23:58:31 +02:00
}
2020-11-14 17:58:56 +01:00
bool ProviderUdp : : init ( const QJsonObject & deviceConfig )
2016-08-23 20:07:12 +02:00
{
2020-07-12 20:27:56 +02:00
bool isInitOK = false ;
2018-12-27 23:11:32 +01:00
2020-07-12 20:27:56 +02:00
// Initialise sub-class
2020-11-14 17:58:56 +01:00
if ( LedDevice : : init ( deviceConfig ) )
2016-08-27 14:05:09 +02:00
{
2020-07-12 20:27:56 +02:00
QString host = deviceConfig [ " host " ] . toString ( _defaultHost ) ;
2020-11-14 17:58:56 +01:00
if ( _address . setAddress ( host ) )
2016-08-27 14:05:09 +02:00
{
2020-11-14 17:58:56 +01:00
Debug ( _log , " Successfully parsed %s as an IP-address. " , QSTRING_CSTR ( _address . toString ( ) ) ) ;
2020-02-10 15:21:58 +01:00
}
else
{
2020-08-09 17:43:23 +02:00
QHostInfo hostInfo = QHostInfo : : fromName ( host ) ;
2020-11-14 17:58:56 +01:00
if ( hostInfo . error ( ) = = QHostInfo : : NoError )
2020-07-12 20:27:56 +02:00
{
2020-08-09 17:43:23 +02:00
_address = hostInfo . addresses ( ) . first ( ) ;
2020-11-14 17:58:56 +01:00
Debug ( _log , " Successfully resolved IP-address (%s) for hostname (%s). " , QSTRING_CSTR ( _address . toString ( ) ) , QSTRING_CSTR ( host ) ) ;
2020-07-12 20:27:56 +02:00
}
else
{
2020-11-14 17:58:56 +01:00
QString errortext = QString ( " Failed resolving IP-address for [%1], (%2) %3 " ) . arg ( host ) . arg ( hostInfo . error ( ) ) . arg ( hostInfo . errorString ( ) ) ;
this - > setInError ( errortext ) ;
2020-08-09 17:43:23 +02:00
isInitOK = false ;
2020-07-12 20:27:56 +02:00
}
2016-08-27 14:05:09 +02:00
}
2016-09-22 00:18:46 +02:00
2020-11-14 17:58:56 +01:00
if ( ! _isDeviceInError )
2020-07-12 20:27:56 +02:00
{
2020-08-09 17:43:23 +02:00
int config_port = deviceConfig [ " port " ] . toInt ( _port ) ;
2020-11-14 17:58:56 +01:00
if ( config_port < = 0 | | config_port > MAX_PORT )
2020-08-09 17:43:23 +02:00
{
2020-11-14 17:58:56 +01:00
QString errortext = QString ( " Invalid target port [%1]! " ) . arg ( config_port ) ;
this - > setInError ( errortext ) ;
2020-08-09 17:43:23 +02:00
isInitOK = false ;
}
else
{
2020-11-14 17:58:56 +01:00
_port = static_cast < quint16 > ( config_port ) ;
2021-11-17 21:30:43 +01:00
Debug ( _log , " UDP socket will write to %s port: %u " , QSTRING_CSTR ( _address . toString ( ) ) , _port ) ;
2018-12-27 23:11:32 +01:00
2020-08-09 17:43:23 +02:00
_udpSocket = new QUdpSocket ( this ) ;
2020-07-12 20:27:56 +02:00
2020-08-09 17:43:23 +02:00
isInitOK = true ;
}
2020-07-12 20:27:56 +02:00
}
}
2020-02-10 15:21:58 +01:00
return isInitOK ;
}
2020-07-12 20:27:56 +02:00
int ProviderUdp : : open ( )
2020-02-10 15:21:58 +01:00
{
2020-07-12 20:27:56 +02:00
int retval = - 1 ;
_isDeviceReady = false ;
2020-02-23 23:18:34 +01:00
2020-06-28 23:05:32 +02:00
// Try to bind the UDP-Socket
2020-11-14 17:58:56 +01:00
if ( _udpSocket ! = nullptr )
2020-02-23 23:18:34 +01:00
{
2020-11-14 17:58:56 +01:00
if ( _udpSocket - > state ( ) ! = QAbstractSocket : : BoundState )
2020-02-23 23:18:34 +01:00
{
2020-08-09 17:43:23 +02:00
QHostAddress localAddress = QHostAddress : : Any ;
quint16 localPort = 0 ;
2020-11-14 17:58:56 +01:00
if ( ! _udpSocket - > bind ( localAddress , localPort ) )
2020-08-09 17:43:23 +02:00
{
2020-11-14 17:58:56 +01:00
QString warntext = QString ( " Could not bind local address: %1, (%2) %3 " ) . arg ( localAddress . toString ( ) ) . arg ( _udpSocket - > error ( ) ) . arg ( _udpSocket - > errorString ( ) ) ;
Warning ( _log , " %s " , QSTRING_CSTR ( warntext ) ) ;
2020-08-09 17:43:23 +02:00
}
2020-02-23 23:18:34 +01:00
}
2020-07-12 20:27:56 +02:00
// Everything is OK, device is ready
_isDeviceReady = true ;
retval = 0 ;
2020-02-23 23:18:34 +01:00
}
2020-07-12 20:27:56 +02:00
else
2020-02-10 15:21:58 +01:00
{
2020-11-14 17:58:56 +01:00
this - > setInError ( " Open error. UDP Socket not initialised! " ) ;
2020-02-10 15:21:58 +01:00
}
return retval ;
}
2020-07-12 20:27:56 +02:00
int ProviderUdp : : close ( )
2020-02-10 15:21:58 +01:00
{
2020-07-12 20:27:56 +02:00
int retval = 0 ;
_isDeviceReady = false ;
2016-05-30 23:58:31 +02:00
2020-11-14 17:58:56 +01:00
if ( _udpSocket ! = nullptr )
2020-02-10 15:21:58 +01:00
{
2020-06-28 23:05:32 +02:00
// Test, if device requires closing
2020-11-14 17:58:56 +01:00
if ( _udpSocket - > isOpen ( ) )
2020-06-28 23:05:32 +02:00
{
2020-11-14 17:58:56 +01:00
Debug ( _log , " Close UDP-device: %s " , QSTRING_CSTR ( this - > getActiveDeviceType ( ) ) ) ;
2020-06-28 23:05:32 +02:00
_udpSocket - > close ( ) ;
// Everything is OK -> device is closed
}
2020-02-10 15:21:58 +01:00
}
2020-07-12 20:27:56 +02:00
return retval ;
2016-05-30 23:58:31 +02:00
}
2020-11-14 17:58:56 +01:00
int ProviderUdp : : writeBytes ( const unsigned size , const uint8_t * data )
2016-05-30 23:58:31 +02:00
{
2020-11-14 17:58:56 +01:00
int rc = 0 ;
qint64 bytesWritten = _udpSocket - > writeDatagram ( reinterpret_cast < const char * > ( data ) , size , _address , _port ) ;
2016-05-30 23:58:31 +02:00
2020-11-14 17:58:56 +01:00
if ( bytesWritten = = - 1 | | bytesWritten ! = size )
{
Warning ( _log , " %s " , QSTRING_CSTR ( QString ( " (%1:%2) Write Error: (%3) %4 " ) . arg ( _address . toString ( ) ) . arg ( _port ) . arg ( _udpSocket - > error ( ) ) . arg ( _udpSocket - > errorString ( ) ) ) ) ;
rc = - 1 ;
}
return rc ;
2016-05-30 23:58:31 +02:00
}
2020-11-01 21:56:19 +01:00
2020-11-14 17:58:56 +01:00
int ProviderUdp : : writeBytes ( const QByteArray & bytes )
2020-11-01 21:56:19 +01:00
{
2020-11-14 17:58:56 +01:00
int rc = 0 ;
qint64 bytesWritten = _udpSocket - > writeDatagram ( bytes , _address , _port ) ;
2020-11-01 21:56:19 +01:00
2020-11-14 17:58:56 +01:00
if ( bytesWritten = = - 1 | | bytesWritten ! = bytes . size ( ) )
{
Warning ( _log , " %s " , QSTRING_CSTR ( QString ( " (%1:%2) Write Error: (%3) %4 " ) . arg ( _address . toString ( ) ) . arg ( _port ) . arg ( _udpSocket - > error ( ) ) . arg ( _udpSocket - > errorString ( ) ) ) ) ;
rc = - 1 ;
}
return rc ;
2020-11-01 21:56:19 +01:00
}