2016-06-25 22:08:17 +02:00
# include <leddevice/LedDevice.h>
2016-10-09 22:22:17 +02:00
# include <sstream>
2016-06-25 22:08:17 +02:00
2016-10-09 22:22:17 +02:00
//QT include
2016-09-10 19:08:08 +02:00
# include <QResource>
# include <QStringList>
# include <QDir>
2017-04-09 22:28:32 +02:00
# include <QDateTime>
2020-02-10 15:21:58 +01:00
# include <QEventLoop>
# include <QTimer>
2017-04-09 22:28:32 +02:00
2017-03-21 17:55:46 +01:00
# include "hyperion/Hyperion.h"
2017-10-12 11:55:03 +02:00
# include <utils/JsonUtils.h>
2016-09-10 19:08:08 +02:00
2019-01-01 19:47:07 +01:00
LedDevice : : LedDevice ( const QJsonObject & config , QObject * parent )
: QObject ( parent )
, _devConfig ( config )
2018-12-27 23:11:32 +01:00
, _log ( Logger : : getInstance ( " LEDDEVICE " ) )
2016-08-14 10:46:44 +02:00
, _ledBuffer ( 0 )
2020-02-10 15:21:58 +01:00
, _deviceReady ( false )
, _deviceInError ( false )
, _refresh_timer ( new QTimer ( this ) )
2016-12-02 12:07:24 +01:00
, _refresh_timer_interval ( 0 )
2017-04-09 22:28:32 +02:00
, _last_write_time ( QDateTime : : currentMSecsSinceEpoch ( ) )
, _latchTime_ms ( 0 )
2017-03-21 17:55:46 +01:00
, _componentRegistered ( false )
2020-02-10 15:21:58 +01:00
, _enabled ( false )
, _refresh_enabled ( false )
2016-06-25 22:08:17 +02:00
{
2020-02-10 15:21:58 +01:00
// setup refreshTimer
_refresh_timer - > setTimerType ( Qt : : PreciseTimer ) ;
_refresh_timer - > setInterval ( _refresh_timer_interval ) ;
connect ( _refresh_timer , SIGNAL ( timeout ( ) ) , this , SLOT ( rewriteLeds ( ) ) ) ;
2016-06-25 22:08:17 +02:00
}
2016-07-13 11:18:12 +02:00
2019-01-01 19:47:07 +01:00
LedDevice : : ~ LedDevice ( )
{
2020-02-10 15:21:58 +01:00
_refresh_timer - > deleteLater ( ) ;
2019-01-01 19:47:07 +01:00
}
2016-07-13 11:18:12 +02:00
int LedDevice : : open ( )
{
2020-02-14 21:58:10 +01:00
int retval = - 1 ;
QString errortext ;
_deviceReady = false ;
// General initialisation and configuration of LedDevice
if ( init ( _devConfig ) )
{
// Everything is OK -> enable device
_deviceReady = true ;
setEnable ( true ) ;
retval = 0 ;
}
return retval ;
2016-07-13 11:18:12 +02:00
}
2016-08-23 20:07:12 +02:00
2020-02-10 15:21:58 +01:00
void LedDevice : : setInError ( const QString & errorMsg )
{
_deviceInError = true ;
_deviceReady = false ;
_enabled = false ;
this - > stopRefreshTimer ( ) ;
Error ( _log , " Device disabled, device '%s' signals error: '%s' " , QSTRING_CSTR ( _activeDeviceType ) , QSTRING_CSTR ( errorMsg ) ) ;
emit enableStateChanged ( _enabled ) ;
}
void LedDevice : : close ( )
{
switchOff ( ) ;
this - > stopRefreshTimer ( ) ;
}
2017-03-21 17:55:46 +01:00
void LedDevice : : setEnable ( bool enable )
{
2020-02-10 15:21:58 +01:00
if ( ! _deviceReady & & enable )
{
Debug ( _log , " Device '%s' was not ready! Trying to re-open. " , QSTRING_CSTR ( _activeDeviceType ) ) ;
if ( open ( ) < 0 )
{
Error ( _log , " Device '%s' cannot be enabled, as it is not ready! " , QSTRING_CSTR ( _activeDeviceType ) ) ;
return ;
}
2020-02-14 21:58:10 +01:00
else
{
// Open worked
_deviceInError = false ;
}
2020-02-10 15:21:58 +01:00
}
2017-09-16 00:18:17 +02:00
// emit signal when state changed
if ( _enabled ! = enable )
2019-07-13 11:23:56 +02:00
{
2017-09-16 00:18:17 +02:00
emit enableStateChanged ( enable ) ;
2019-07-13 11:23:56 +02:00
}
// switch off device when disabled, default: set black to leds when they should go off
2017-03-21 17:55:46 +01:00
if ( _enabled & & ! enable )
2019-07-13 11:23:56 +02:00
{
2017-03-21 17:55:46 +01:00
switchOff ( ) ;
2019-07-13 11:23:56 +02:00
}
else
{
// switch on device when enabled
if ( ! _enabled & & enable )
{
switchOn ( ) ;
}
}
2017-03-21 17:55:46 +01:00
_enabled = enable ;
}
2020-02-10 15:21:58 +01:00
void LedDevice : : setActiveDeviceType ( const QString & deviceType )
2016-08-23 20:07:12 +02:00
{
2019-12-08 13:12:01 +01:00
_activeDeviceType = deviceType ;
2016-09-10 19:08:08 +02:00
}
2016-12-02 12:07:24 +01:00
bool LedDevice : : init ( const QJsonObject & deviceConfig )
{
2020-02-14 21:58:10 +01:00
//Debug(_log, "deviceConfig: [%s]", QString(QJsonDocument(_devConfig).toJson(QJsonDocument::Compact)).toUtf8().constData() );
2018-12-27 23:11:32 +01:00
_colorOrder = deviceConfig [ " colorOrder " ] . toString ( " RGB " ) ;
2019-12-08 13:12:01 +01:00
_activeDeviceType = deviceConfig [ " type " ] . toString ( " file " ) . toLower ( ) ;
2020-02-10 15:21:58 +01:00
setLedCount ( static_cast < unsigned int > ( deviceConfig [ " currentLedCount " ] . toInt ( 1 ) ) ) ; // property injected to reflect real led count
_latchTime_ms = deviceConfig [ " latchTime " ] . toInt ( _latchTime_ms ) ;
_refresh_timer_interval = deviceConfig [ " rewriteTime " ] . toInt ( _refresh_timer_interval ) ;
2018-12-27 23:11:32 +01:00
2020-02-10 15:21:58 +01:00
if ( _refresh_timer_interval > 0 )
2017-04-09 22:28:32 +02:00
{
2020-02-10 15:21:58 +01:00
_refresh_enabled = true ;
if ( _refresh_timer_interval < = _latchTime_ms )
{
int new_refresh_timer_interval = _latchTime_ms + 10 ;
Warning ( _log , " latchTime(%d) is bigger/equal rewriteTime(%d), set rewriteTime to %dms " , _latchTime_ms , _refresh_timer_interval , new_refresh_timer_interval ) ;
_refresh_timer_interval = new_refresh_timer_interval ;
_refresh_timer - > setInterval ( _refresh_timer_interval ) ;
}
//Debug(_log, "Refresh interval = %dms",_refresh_timer_interval );
_refresh_timer - > setInterval ( _refresh_timer_interval ) ;
_last_write_time = QDateTime : : currentMSecsSinceEpoch ( ) ;
2017-04-09 22:28:32 +02:00
2020-02-10 15:21:58 +01:00
this - > startRefreshTimer ( ) ;
}
2016-12-02 12:07:24 +01:00
return true ;
}
2020-02-10 15:21:58 +01:00
void LedDevice : : startRefreshTimer ( )
2016-09-23 08:49:22 +02:00
{
2020-02-10 15:21:58 +01:00
if ( _deviceReady )
{
_refresh_timer - > start ( ) ;
}
}
2017-03-21 17:55:46 +01:00
2020-02-10 15:21:58 +01:00
void LedDevice : : stopRefreshTimer ( )
{
_refresh_timer - > stop ( ) ;
}
2016-11-29 23:14:15 +01:00
2020-02-10 15:21:58 +01:00
int LedDevice : : updateLeds ( const std : : vector < ColorRgb > & ledValues )
{
int retval = 0 ;
2020-02-14 21:58:10 +01:00
if ( ! _deviceReady | | _deviceInError )
2016-11-29 23:14:15 +01:00
{
2020-02-23 23:18:34 +01:00
//std::cout << "LedDevice::updateLeds(), LedDevice NOT ready!" << std::endl;
2020-02-10 15:21:58 +01:00
return - 1 ;
2016-11-29 23:14:15 +01:00
}
2020-02-10 15:21:58 +01:00
else
2017-04-09 22:28:32 +02:00
{
2020-02-10 15:21:58 +01:00
qint64 elapsedTime = QDateTime : : currentMSecsSinceEpoch ( ) - _last_write_time ;
if ( _latchTime_ms = = 0 | | elapsedTime > = _latchTime_ms )
{
//std::cout << "LedDevice::updateLeds(), Elapsed time since last write (" << elapsedTime << ") ms > _latchTime_ms (" << _latchTime_ms << ") ms" << std::endl;
retval = write ( ledValues ) ;
_last_write_time = QDateTime : : currentMSecsSinceEpoch ( ) ;
// if device requires refreshing, save Led-Values and restart the timer
if ( _refresh_enabled )
{
this - > startRefreshTimer ( ) ;
_last_ledValues = ledValues ;
}
}
else
{
//std::cout << "LedDevice::updateLeds(), Skip write. _latchTime_ms (" << _latchTime_ms << ") ms > elapsedTime (" << elapsedTime << ") ms" << std::endl;
if ( _refresh_enabled )
{
//Stop timer to allow for next non-refresh update
this - > stopRefreshTimer ( ) ;
}
}
2017-09-16 00:18:17 +02:00
}
2017-04-09 22:28:32 +02:00
return retval ;
2016-09-23 08:49:22 +02:00
}
2019-12-08 13:12:01 +01:00
int LedDevice : : writeBlack ( )
2016-09-23 08:49:22 +02:00
{
2020-02-10 15:21:58 +01:00
return _deviceReady ? updateLeds ( std : : vector < ColorRgb > ( static_cast < unsigned long > ( _ledCount ) , ColorRgb : : BLACK ) ) : - 1 ;
2016-09-23 08:49:22 +02:00
}
2019-12-08 13:12:01 +01:00
int LedDevice : : switchOff ( )
{
2020-02-10 15:21:58 +01:00
// Stop refresh timer to ensure that "write Black" is executed
this - > stopRefreshTimer ( ) ;
if ( _latchTime_ms > 0 )
{
// Wait latchtime before writing black
QEventLoop loop ;
QTimer : : singleShot ( _latchTime_ms , & loop , SLOT ( quit ( ) ) ) ;
loop . exec ( ) ;
}
2019-12-08 13:12:01 +01:00
int rc = writeBlack ( ) ;
return rc ;
}
2017-09-16 00:18:17 +02:00
int LedDevice : : switchOn ( )
{
return 0 ;
}
2016-09-23 08:49:22 +02:00
2020-02-10 15:21:58 +01:00
void LedDevice : : setLedCount ( unsigned int ledCount )
2016-10-08 08:14:36 +02:00
{
_ledCount = ledCount ;
_ledRGBCount = _ledCount * sizeof ( ColorRgb ) ;
_ledRGBWCount = _ledCount * sizeof ( ColorRgbw ) ;
}
2016-11-29 23:14:15 +01:00
2020-03-26 18:49:44 +01:00
void LedDevice : : setLatchTime ( int latchTime_ms )
{
_latchTime_ms = latchTime_ms ;
Debug ( _log , " LatchTime updated to %dms " , this - > getLatchTime ( ) ) ;
}
2016-11-29 23:14:15 +01:00
int LedDevice : : rewriteLeds ( )
{
2020-02-10 15:21:58 +01:00
int retval = - 1 ;
if ( _deviceReady )
{
//qint64 elapsedTime = QDateTime::currentMSecsSinceEpoch() - _last_write_time;
//std::cout << "LedDevice::rewriteLeds(): Rewrite Leds now, elapsedTime [" << elapsedTime << "] ms" << std::endl;
// //:TESTING: Inject "white" output records to differentiate from normal writes
// _last_ledValues.clear();
// _last_ledValues.resize(static_cast<unsigned long>(_ledCount), ColorRgb::WHITE);
// printLedValues(_last_ledValues);
// //:TESTING:
retval = write ( _last_ledValues ) ;
_last_write_time = QDateTime : : currentMSecsSinceEpoch ( ) ;
}
else
{
// If Device is not ready stop timer
this - > stopRefreshTimer ( ) ;
}
return retval ;
2016-11-29 23:14:15 +01:00
}
2019-12-08 13:12:01 +01:00
2020-02-10 15:21:58 +01:00
void LedDevice : : printLedValues ( const std : : vector < ColorRgb > & ledValues )
{
std : : cout < < " LedValues [ " < < ledValues . size ( ) < < " ] [ " ;
for ( const ColorRgb & color : ledValues )
{
std : : cout < < color ;
}
std : : cout < < " ] " < < std : : endl ;
}