mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
f955af29fd
* Fix Nanoleaf - Udp Network init was missing * ProviderUdp - Add init error handling
268 lines
6.5 KiB
C++
268 lines
6.5 KiB
C++
#include <leddevice/LedDevice.h>
|
|
#include <sstream>
|
|
|
|
//QT include
|
|
#include <QResource>
|
|
#include <QStringList>
|
|
#include <QDir>
|
|
#include <QDateTime>
|
|
#include <QEventLoop>
|
|
#include <QTimer>
|
|
|
|
#include "hyperion/Hyperion.h"
|
|
#include <utils/JsonUtils.h>
|
|
|
|
LedDevice::LedDevice(const QJsonObject& config, QObject* parent)
|
|
: QObject(parent)
|
|
, _devConfig(config)
|
|
, _log(Logger::getInstance("LEDDEVICE"))
|
|
, _ledBuffer(0)
|
|
, _deviceReady(false)
|
|
, _deviceInError(false)
|
|
, _refresh_timer(new QTimer(this))
|
|
, _refresh_timer_interval(0)
|
|
, _last_write_time(QDateTime::currentMSecsSinceEpoch())
|
|
, _latchTime_ms(0)
|
|
, _componentRegistered(false)
|
|
, _enabled(false)
|
|
, _refresh_enabled (false)
|
|
{
|
|
// setup refreshTimer
|
|
_refresh_timer->setTimerType(Qt::PreciseTimer);
|
|
_refresh_timer->setInterval( _refresh_timer_interval );
|
|
connect(_refresh_timer, SIGNAL(timeout()), this, SLOT(rewriteLeds()));
|
|
}
|
|
|
|
LedDevice::~LedDevice()
|
|
{
|
|
_refresh_timer->deleteLater();
|
|
}
|
|
|
|
int LedDevice::open()
|
|
{
|
|
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;
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
void LedDevice::setEnable(bool enable)
|
|
{
|
|
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;
|
|
}
|
|
else
|
|
{
|
|
// Open worked
|
|
_deviceInError = false;
|
|
}
|
|
}
|
|
|
|
// emit signal when state changed
|
|
if (_enabled != enable)
|
|
{
|
|
emit enableStateChanged(enable);
|
|
}
|
|
// switch off device when disabled, default: set black to leds when they should go off
|
|
if ( _enabled && !enable)
|
|
{
|
|
switchOff();
|
|
}
|
|
else
|
|
{
|
|
// switch on device when enabled
|
|
if ( !_enabled && enable)
|
|
{
|
|
switchOn();
|
|
}
|
|
}
|
|
_enabled = enable;
|
|
}
|
|
|
|
void LedDevice::setActiveDeviceType(const QString& deviceType)
|
|
{
|
|
_activeDeviceType = deviceType;
|
|
}
|
|
|
|
bool LedDevice::init(const QJsonObject &deviceConfig)
|
|
{
|
|
//Debug(_log, "deviceConfig: [%s]", QString(QJsonDocument(_devConfig).toJson(QJsonDocument::Compact)).toUtf8().constData() );
|
|
|
|
_colorOrder = deviceConfig["colorOrder"].toString("RGB");
|
|
_activeDeviceType = deviceConfig["type"].toString("file").toLower();
|
|
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);
|
|
|
|
if ( _refresh_timer_interval > 0 )
|
|
{
|
|
_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();
|
|
|
|
this->startRefreshTimer();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void LedDevice::startRefreshTimer()
|
|
{
|
|
if ( _deviceReady)
|
|
{
|
|
_refresh_timer->start();
|
|
}
|
|
}
|
|
|
|
void LedDevice::stopRefreshTimer()
|
|
{
|
|
_refresh_timer->stop();
|
|
}
|
|
|
|
int LedDevice::updateLeds(const std::vector<ColorRgb>& ledValues)
|
|
{
|
|
int retval = 0;
|
|
if ( !_deviceReady || _deviceInError)
|
|
{
|
|
//std::cout << "LedDevice::updateLeds(), LedDevice NOT ready!" << std::endl;
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
int LedDevice::writeBlack()
|
|
{
|
|
return _deviceReady ? updateLeds(std::vector<ColorRgb>(static_cast<unsigned long>(_ledCount), ColorRgb::BLACK )) : -1;
|
|
}
|
|
|
|
int LedDevice::switchOff()
|
|
{
|
|
// 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();
|
|
}
|
|
int rc = writeBlack();
|
|
return rc;
|
|
}
|
|
|
|
int LedDevice::switchOn()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void LedDevice::setLedCount(unsigned int ledCount)
|
|
{
|
|
_ledCount = ledCount;
|
|
_ledRGBCount = _ledCount * sizeof(ColorRgb);
|
|
_ledRGBWCount = _ledCount * sizeof(ColorRgbw);
|
|
}
|
|
|
|
int LedDevice::rewriteLeds()
|
|
{
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|